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() и корректные заголовки ответа.
