Разработка GraphQL API для 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка GraphQL API для 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка GraphQL API для 1С-Битрикс

GraphQL решает конкретную проблему REST API: клиент получает либо слишком мало данных (underfetching — нужно несколько запросов), либо слишком много (overfetching — поля, которые никому не нужны). В GraphQL клиент сам описывает, какие поля ему нужны, и получает ровно то, что запросил. Для 1С-Битрикс это особенно актуально при работе с вложенными структурами: товар → торговые предложения → цены → остатки — всё в одном запросе.

Почему GraphQL, а не REST

REST-эндпоинт /api/products/123 возвращает фиксированный набор полей. Мобильному приложению нужны имя и цена — оно получает 40 полей. Другому клиенту нужны остатки по складам — он делает второй запрос. GraphQL позволяет каждому клиенту описать свои потребности:

# Мобильное приложение
query {
  product(id: 123) {
    name
    price { value currency }
    images { url }
  }
}

# Складской модуль
query {
  product(id: 123) {
    name
    sku { id stock { warehouse quantity } }
  }
}

Один эндпоинт, один запрос — разные данные для разных клиентов.

Интеграция GraphQL с Битрикс

Битрикс не поддерживает GraphQL из коробки. Реализация строится поверх стандартного PHP Битрикс через библиотеку webonyx/graphql-php — это де-факто стандарт для PHP.

Точка входа — один контроллер на URL /api/graphql, который принимает POST-запросы с JSON-телом ({ "query": "...", "variables": {...} }).

// /local/php_interface/api/graphql.php
use GraphQL\GraphQL;
use GraphQL\Type\Schema;

$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);

$schema = new Schema([
    'query' => QueryType::build(),
    'mutation' => MutationType::build(),
]);

$result = GraphQL::executeQuery($schema, $input['query'], null, null, $input['variables'] ?? null);
header('Content-Type: application/json');
echo json_encode($result->toArray());

Схема типов для Битрикс

Каждый тип GraphQL соответствует сущности Битрикс. Пример для каталога:

// ProductType
ObjectType(['name' => 'Product', 'fields' => fn() => [
    'id' => ['type' => Type::int()],
    'name' => ['type' => Type::string()],
    'code' => ['type' => Type::string()],
    'price' => [
        'type' => PriceType::get(),
        'resolve' => fn($product) => PriceResolver::resolve($product['ID']),
    ],
    'sku' => [
        'type' => Type::listOf(SkuType::get()),
        'resolve' => fn($product) => SkuResolver::resolve($product['ID']),
    ],
    'sections' => [
        'type' => Type::listOf(SectionType::get()),
        'resolve' => fn($product) => SectionResolver::resolve($product['IBLOCK_SECTION_ID']),
    ],
]]);

Резолверы (resolvers) — функции, которые получают данные для каждого поля. Резолвер для price обращается к b_catalog_price, для sku — к дочернему инфоблоку SKU, для sections — к b_iblock_section.

Проблема N+1 и DataLoader

Главная проблема GraphQL — N+1 запросов. Клиент запросил список из 20 товаров, для каждого нужны цены — 20 отдельных запросов к b_catalog_price. Решение: DataLoader (паттерн batching).

DataLoader накапливает запросы в рамках одного GraphQL-выполнения и делает один батч-запрос:

class PriceDataLoader
{
    private array $buffer = [];

    public function load(int $productId): Promise
    {
        $this->buffer[] = $productId;
        return new Promise(fn($resolve) => $resolve($productId));
    }

    public function dispatch(): void
    {
        // Один запрос для всех накопленных ID
        $prices = \Bitrix\Catalog\PriceTable::getList([
            'filter' => ['PRODUCT_ID' => $this->buffer],
        ])->fetchAll();
        // Распределяем результаты
    }
}

Вместо 20 запросов — 1. Для вложенных данных (товары → SKU → остатки) экономия кратная.

Мутации: создание и обновление данных

Мутации в GraphQL — аналог POST/PUT/DELETE в REST:

mutation {
  createOrder(input: {
    productId: 123,
    quantity: 2,
    deliveryAddress: "Москва, ул. Ленина, 1"
  }) {
    orderId
    status
    totalAmount
  }
}

Резолвер мутации вызывает \Bitrix\Sale\Order::create() с нужными параметрами — стандартное D7 API модуля sale.

Авторизация и разграничение доступа

Авторизация реализуется на двух уровнях:

Уровень запроса. Middleware проверяет JWT или сессию Битрикс перед выполнением GraphQL-запроса.

Уровень поля. Конкретное поле доступно только авторизованным пользователям. Например, поле costPrice (себестоимость) видит только пользователь с ролью «Администратор». Реализуется в резолвере:

'costPrice' => [
    'type' => Type::float(),
    'resolve' => function($product, $args, Context $context) {
        if (!$context->user->hasRole('admin')) {
            throw new \Exception('Нет доступа');
        }
        return $product['COST_PRICE'];
    },
],

Кеширование GraphQL

GraphQL сложнее кешировать, чем REST: запросы уникальны по набору полей и переменных. Подходы:

  • Кеш на уровне резолвера (наиболее распространённый): резолвер кеширует результат конкретного DataLoader-батча в Redis/Memcache. TTL зависит от частоты обновления данных.
  • Persisted Queries: клиент отправляет хеш заранее зарегистрированного запроса вместо полного текста. Это позволяет кешировать на уровне HTTP (CDN кеширует GET-запросы с хешем).
  • Тегированный кеш Битрикс: регистрируем теги при чтении данных (iblock_id_1), инвалидируем при изменении.

Подписки (Subscriptions)

GraphQL поддерживает подписки — реalttime обновления через WebSocket. При изменении заказа все подписчики получают уведомление. Для Битрикс реализуется через отдельный WebSocket-сервер (Ratchet/Swoole) + Redis pub/sub. При изменении сущности в Битрикс (через обработчик события) публикуем в Redis-канал, WebSocket-сервер доставляет всем подписчикам.

Introspection и документация

GraphQL предоставляет introspection — клиент может запросить полную схему API. На её основе GraphiQL (браузерный IDE) позволяет изучать API интерактивно. Для разработки это незаменимо: типы, описания, автодополнение запросов.

Этапы разработки

Этап Содержание Срок
Проектирование схемы Типы, запросы, мутации, связи 1 неделя
Базовая инфраструктура GraphQL endpoint, авторизация 3–5 дней
Реализация типов и резолверов Каталог, заказы, пользователи 2–4 недели
DataLoader (N+1) Batching для вложенных данных 1 неделя
Кеширование Redis DataLoader cache 1 неделя
Авторизация полей Разграничение доступа 3–5 дней
Тестирование Unit-тесты резолверов, интеграционные тесты 1 неделя

GraphQL на Битрикс — зрелое решение для проектов с несколькими клиентами и сложными вложенными данными. Для простого сайта с одним фронтендом — REST достаточно.