Весь HTML-код, который генерируется на странице Битрикс, не отправляется в браузер сразу.
Он накапливается в специальном буфере вывода.
Только после того, как отработает эпилог (epilog_after.php), Битрикс выполняет финальные действия (например, заменяет отложенные функции) и отправляет весь накопленный HTML пользователю.
Как и зачем работает буферизация?
В файле /bitrix/modules/main/include/prolog_before.php, который подключается для инициализации ядра, неявно вызывается PHP-функция ob_start().
Она «включает» буферизацию.
Это необходимо для:
- Отложенных функций: Позволяет в теле страницы вызывать $APPLICATION->SetTitle() или $APPLICATION->AddHeadScript(), а Битрикс вставит результат в <head> в самом конце.
- События OnEndBufferContent: Дает возможность модулям изменять финальный HTML страницы перед отправкой в браузер.
- Управления кэшированием.
Проблема: Зачем нужен «чистый» вывод?
Когда вы создаете скрипт для AJAX-запроса или для генерации файла (PDF, CSV), вам не нужен стандартный HTML-шаблон сайта.
Вам нужен «чистый» ответ — только JSON-строка или бинарное содержимое файла.
Если в AJAX-скрипте просто написать echo json_encode(…), вы получите «мусорный» ответ, который сломает ваш JavaScript:
<!DOCTYPE html>...
<head>...</head>
<body>
...
{"status":"success","data":"my_data"} <!-- <- Только эта часть вам нужна -->
...
</body>
</html>
Решение: $APPLICATION->RestartBuffer()
Метод $APPLICATION->RestartBuffer() — это стандартный и единственно правильный способ решить эту проблему. Он выполняет два действия:
- Очищает буфер: Вызывает ob_end_clean(), полностью удаляя весь HTML, накопленный с момента подключения пролога.
- Прекращает выполнение: Регистрирует функцию, которая вызовет die() в конце хита, гарантируя, что никакой лишний код (например, эпилог) не будет выполнен.
Практический пример 1: AJAX-обработчик
Создадим файл /ajax/get_time.php, который будет возвращать текущее время в формате JSON.
// /ajax/get_time.php
// Подключаем ядро для доступа к API Битрикс
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// Проверяем права, сессию, входные данные...
if (!check_bitrix_sessid() || !$USER->IsAuthorized()) {
// В этом случае можно не очищать буфер, а просто завершить работу.
// Битрикс вернет стандартный HTML-ответ с ошибкой доступа.
return;
}
global $APPLICATION;
$APPLICATION->RestartBuffer(); // <-- Ключевой момент! Очищаем всё, что вывел пролог.
$data = [
'time' => (new \Bitrix\Main\Type\DateTime())->format('H:i:s'),
'status' => 'ok'
];
// Устанавливаем правильный заголовок для JSON
header('Content-Type: application/json');
// Выводим ТОЛЬКО наши данные
echo json_encode($data);
// Явно вызывать die() не нужно, RestartBuffer сделает это за нас.
Практический пример 2: Генерация CSV-файла
Логика абсолютно та же: подключить ядро, выполнить логику, очистить буфер и вывести содержимое файла.
// /admin/tools/export_users.php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
global $APPLICATION, $USER;
if (!$USER->IsAdmin()) return;
$APPLICATION->RestartBuffer();
// Заголовки для скачивания файла
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="users.csv"');
$output = fopen('php://output', 'w');
fputcsv($output, ['ID', 'LOGIN', 'EMAIL'], ';'); // Заголовки CSV
$rsUsers = CUser::GetList($by='id', $order='asc', ['ACTIVE' => 'Y']);
while($arUser = $rsUsers->Fetch()) {
fputcsv($output, [$arUser['ID'], $arUser['LOGIN'], $arUser['EMAIL']], ';');
}
// die() не нужен
RestartBuffer vs. die() — В чем разница?
Код | Результат |
echo ‘A’; die(); | В браузер отправится весь накопленный буфер (включая HTML из header.php) + символ ‘A’. |
echo ‘A’; RestartBuffer(); | Буфер будет очищен, die() будет вызван позже. В итоге ответ будет пустым, так как ‘A’ было выведено до очистки. |
RestartBuffer(); echo ‘A’; | Буфер очищен, затем в него помещается ‘A’. В конце хита ‘A’ отправляется в браузер. Это правильный порядок. |
Важный нюанс для AJAX-компонентов: ShowAjaxHead()
Когда вы перезагружаете компонент через AJAX (runComponentAction), Битриксу может понадобиться подключить новые CSS или JS файлы, которые используются в шаблоне. Просто вернуть HTML будет недостаточно.
Для этого существует метод $APPLICATION->ShowAjaxHead(). Он возвращает специальные JSON-данные с ассетами. Его нужно вызывать до RestartBuffer.
// В action-методе компонента (class.php)
public function reloadAction()
{
// ... логика ...
// Готовим ассеты для frontend'а
$this->executeComponent();
global $APPLICATION;
// Собираем данные об ассетах
$assets = \Bitrix\Main\Page\Asset::getInstance()->getJs();
// ... и для CSS, и для строк
// Очищаем буфер
$APPLICATION->RestartBuffer();
// Отдаем JSON, который поймет BX.ajax
header('Content-Type: application/json');
echo json_encode([
'html' => $this->getTemplateHtml(), // HTML компонента, который был в буфере до очистки
'assets' => [
'js' => $assets,
// ...
]
]);
// ...
}
Вывод:
$APPLICATION->RestartBuffer() — это обязательный инструмент для создания «чистых» ответов в AJAX-скриптах и генераторах файлов, которым нужен доступ к API Битрикс.
Всегда используйте его после всех проверок и до вывода основного контента.
Это гарантирует, что ваш frontend получит именно те данные, которые ожидает, без лишнего HTML-кода.
буферизация Битрикс, RestartBuffer, $APPLICATION, ShowAjaxHead, AJAX, JSON, очистка буфера, prolog_before, генерация файлов.