Разработка AJAX-контроллеров 1С-Битрикс
Компонент Битрикс выводит список товаров с кнопкой «Показать ещё». При клике страница перезагружается целиком — или разработчик прикрутил jQuery-запрос на /ajax.php?action=load_more, который принимает POST-данные и возвращает HTML из буфера компонента. Это рабочий, но архаичный подход. Битрикс D7 предоставляет контроллеры — \Bitrix\Main\Engine\Controller — которые дают структурированный способ создания AJAX-эндпоинтов с авторизацией, CSRF-защитой и стандартным форматом ответа.
Чем контроллер D7 лучше самописного ajax.php
Самописный ajax.php — концентрация рисков: нет централизованной CSRF-проверки, нет стандартной обработки ошибок, нет автоматической авторизации, код разбросан по файлам. Контроллер D7 решает всё это из коробки:
namespace MyVendor\Catalog\Controller;
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Engine\ActionFilter;
class Product extends Controller
{
public function configureActions(): array
{
return [
'getList' => [
'prefilters' => [
new ActionFilter\Authentication(), // проверка авторизации
new ActionFilter\Csrf(), // CSRF-токен
],
],
];
}
public function getListAction(int $sectionId, int $page = 1): array
{
// Возвращаем массив — Битрикс сам обернёт в {"status":"success","data":{...}}
return [
'items' => $this->loadProducts($sectionId, $page),
'total' => $this->countProducts($sectionId),
];
}
}
Фреймворк автоматически оборачивает возвращаемое значение в JSON-конверт {"status": "success", "data": {...}} или {"status": "error", "errors": [...]} при выброшенном исключении.
Регистрация контроллера
Контроллер регистрируется в файле роутинга модуля routes.php:
// В .settings.php модуля или через метод Application::getInstance()->getRouter()
\Bitrix\Main\Routing\RoutingConfigurator::registerRoutes(function($routes) {
$routes->post('/api/catalog/product/get-list/', 'MyVendor\Catalog\Controller\Product::getListAction');
});
Альтернативный способ — через стандартный механизм компонентов: контроллер вызывается через /bitrix/services/main/ajax.php?action=myvendor:catalog.product.getList.
Детально: фильтры и middleware
Контроллер поддерживает цепочку фильтров до и после выполнения действия. Это аналог middleware в Laravel.
Стандартные prefilters:
-
ActionFilter\Authentication— требует авторизации -
ActionFilter\Csrf— проверяет CSRF-токен (bitrix_sessid) -
ActionFilter\HttpMethod— ограничивает методы (GET/POST) -
ActionFilter\Scope— ограничивает контекст (только веб, только REST, только CLI)
Кастомный фильтр — например, проверка прав на конкретный ресурс:
class ResourceAccessFilter extends \Bitrix\Main\Engine\ActionFilter\Base
{
public function onBeforeAction(Event $event): ?EventResult
{
$action = $event->getParameter('action');
$sectionId = $action->getController()->getRequest()->getPost('sectionId');
if (!SectionAccessChecker::canRead((int)$sectionId)) {
$this->addError(new \Bitrix\Main\Error('Access denied', 403));
return new EventResult(EventResult::ERROR, null, null, $this);
}
return null;
}
}
Обработка файлов и сложных данных
Контроллер автоматически десериализует входящие данные. Для загрузки файлов — через $this->getRequest()->getFile('image'), результат — объект \Bitrix\Main\Web\Upload\UploadedFile с методами валидации типа и размера.
Для пагинации используется встроенный объект \Bitrix\Main\Engine\Response\DataType\Page:
public function getListAction(int $page): \Bitrix\Main\Engine\Response\DataType\Page
{
$pageSize = 20;
$items = ProductTable::getList([
'limit' => $pageSize,
'offset' => ($page - 1) * $pageSize,
])->fetchAll();
return new \Bitrix\Main\Engine\Response\DataType\Page('items', $items, fn() => ProductTable::getCount());
}
Тестирование контроллеров
Контроллеры D7 можно тестировать через PHPUnit без HTTP-запроса: создаётся экземпляр контроллера, подменяется Request, вызывается run(). Это большой плюс по сравнению с самописными ajax.php, которые тестировать сложно.
Сроки разработки
| Масштаб | Состав | Срок |
|---|---|---|
| Базовый | 5–10 эндпоинтов + стандартные фильтры | 1–2 недели |
| Средний | + кастомные фильтры + файловая загрузка + rate limiting | 3–4 недели |
| Расширенный | + версионирование + документация OpenAPI + тесты | 5–7 недель |
Если на проекте уже есть самописные ajax.php, их стоит мигрировать на контроллеры постепенно, начиная с наиболее нагруженных или проблемных эндпоинтов.







