Главная » Разработка Битрикс » AJAX в Битрикс: BX.ajax, ajax_mode и контроллеры D7

AJAX в Битрикс: BX.ajax, ajax_mode и контроллеры D7

Схема AJAX-запроса в Битрикс: запрос от браузера обрабатывает контроллер D7 и возвращает JSON

AJAX на сайте под 1С-Битрикс можно сделать пятью разными способами, и они сильно отличаются по надёжности. Часть решений тянется из старого ядра, часть появилась в D7, а самый распространённый вариант — отдельный PHP-файл в обход системы — работает, но обычно оказывается худшим выбором.

Разберём все подходы, покажем современный вариант с контроллерами D7 и объясним, почему подключать prolog_before.php в самописный обработчик — плохая идея.

Обзор подходов

Способ Когда уместен
Параметр AJAX_MODE компонента Готовые компоненты: пагинация, фильтр
Отдельный файл-обработчик Быстрое решение, но требует ручной защиты
Обработка внутри компонента Логика относится к конкретному компоненту
Контроллеры D7 Рекомендуемый вариант для нового кода
ajax.php модуля Своё готовое решение или модуль

Готовые компоненты: AJAX_MODE

Самый простой случай. У многих штатных компонентов есть параметр, включающий подгрузку без перезагрузки страницы:

<?$APPLICATION->IncludeComponent(
    'bitrix:news.list',
    'main',
    [
        'IBLOCK_ID'         => 5,
        'AJAX_MODE'         => 'Y',
        'AJAX_OPTION_JUMP'  => 'N',
        'AJAX_OPTION_STYLE' => 'Y',
        'AJAX_OPTION_HISTORY' => 'N',
    ]
)?>

Ничего писать не нужно, но и гибкости нет: работает только то, что предусмотрено разработчиками компонента.

Нужна помощь с Битрикс?





    Отдельный файл — и почему он проблемный

    Классическое решение, которое встречается в большинстве проектов:

    <?php // /local/ajax/handler.php — так делать не стоит
    
    require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
    
    $result = ['success' => true];
    
    echo json_encode($result);
    
    require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');

    Работает, но приносит с собой набор проблем:

    • Загружается всё ядро целиком — это медленно для простого ответа.
    • Нет автоматической проверки CSRF. Защиту нужно делать руками, и её часто забывают.
    • Нет проверки прав — тоже вручную.
    • Файл доступен напрямую по URL любому желающему.
    • Разбор параметров и формирование ответа пишутся заново каждый раз.

    Если такой обработчик всё же нужен, минимальная защита обязательна — проверка токена сессии:

    <?php
    
    if (!check_bitrix_sessid()) {
        http_response_code(403);
        echo json_encode(['error' => 'Неверный токен']);
        die();
    }

    А на стороне клиента токен нужно передать:

    <input type="hidden" name="sessid" value="<?= bitrix_sessid() ?>">

    Контроллеры D7 — правильный путь

    В новом ядре для AJAX есть штатный механизм: контроллер с методами-действиями. Он сам разбирает параметры, проверяет токен, формирует JSON и обрабатывает ошибки.

    Создаём контроллер:

    <?php // /local/php_interface/classes/Controller/Feedback.php
    
    namespace Project\Controller;
    
    use Bitrix\Main\Engine\Controller;
    use Bitrix\Main\Engine\ActionFilter;
    
    class Feedback extends Controller
    {
        // какие проверки применяются к действиям
        protected function getDefaultPreFilters()
        {
            return [
                new ActionFilter\HttpMethod([ActionFilter\HttpMethod::METHOD_POST]),
                new ActionFilter\Csrf(),
            ];
        }
    
        public function sendAction(string $name, string $phone): array
        {
            if (empty($name)) {
                $this->addError(new \Bitrix\Main\Error('Не указано имя'));
                return [];
            }
    
            // ... сохранение заявки ...
    
            return ['status' => 'ok'];
        }
    }

    Регистрируем класс в init.php:

    <?php
    
    use Bitrix\Main\Loader;
    
    Loader::registerAutoLoadClasses(null, [
        'Project\\Controller\\Feedback' => '/local/php_interface/classes/Controller/Feedback.php',
    ]);

    Вызываем с фронтенда:

    BX.ajax.runAction('project:controller.feedback.send', {
        data: {
            name:  'Иван',
            phone: '+79001234567'
        }
    }).then(function (response) {
        console.log(response.data);
    }, function (response) {
        console.log(response.errors);
    });

    Что даёт этот подход: проверка CSRF включается одной строкой, параметры действия приходят типизированными аргументами, ошибки возвращаются в едином формате, а метод HTTP ограничивается фильтром. Всё то, что в самописном обработчике приходится делать руками.

    Формат ответа

    Контроллер всегда возвращает одинаковую структуру:

    {
        "status": "success",
        "data": { "status": "ok" },
        "errors": []
    }

    При ошибке status становится error, а описания попадают в массив errors. Клиентскому коду не нужно гадать, что пришло.

    AJAX внутри компонента

    Если логика относится к конкретному компоненту, обработку можно оставить внутри него. В class.php добавляется проверка на AJAX-запрос:

    <?php
    
    public function executeComponent()
    {
        if ($this->request->isAjaxRequest() && check_bitrix_sessid()) {
            $this->handleAjax();
            return;
        }
    
        $this->includeComponentTemplate();
    }

    Подход удобен тем, что код живёт рядом с компонентом. Устройство компонентов разобрано в статье Создание компонента в Битрикс.

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

    Отдельная тонкость: ответы AJAX не должны кешироваться браузером и промежуточными прокси. Иначе пользователь получит устаревшие данные.

    Контроллеры D7 отдают корректные заголовки сами. Для самописных обработчиков их нужно задать:

    <?php
    
    header('Content-Type: application/json; charset=UTF-8');
    header('Cache-Control: no-store, no-cache, must-revalidate');

    Учтите также композитный кеш: если AJAX меняет содержимое страницы, оно может конфликтовать с закешированной версией. Как устроен композит, описано в статье Композитный сайт Битрикс.

    Частые ошибки

    • Нет проверки CSRF. Обработчик можно вызвать с любого стороннего сайта.
    • Нет проверки прав. Действие, доступное только авторизованным, выполняет кто угодно.
    • Вывод в обработчике до JSON. Любой лишний символ ломает разбор ответа на клиенте — включая пробел после ?>.
    • Ошибки PHP попадают в ответ. Клиент получает HTML с текстом ошибки вместо JSON и падает на разборе.
    • Полная загрузка ядра ради мелочи. Для простой проверки это избыточно.
    • Данные не экранируются. Всё, что пришло от пользователя, обязано проходить проверку перед записью в базу.

    Итог

    Для нового кода на 1С-Битрикс правильный выбор — контроллеры D7: Bitrix\Main\Engine\Controller с фильтрами и вызовом через BX.ajax.runAction(). Они закрывают проверку токена, разбор параметров и формат ответа штатными средствами.

    Отдельный файл с подключением пролога работает, но требует ручной защиты и грузит всё ядро. Если он уже есть в проекте, минимум, который нужно добавить, — проверка check_bitrix_sessid() и корректные заголовки ответа.

    Нужна помощь с Битрикс?

    Исправим ошибку, доработаем сайт, ускорим Битрикс или поможем разобраться с проблемой.

    Услуги
    Инструменты
    База знаний