Ловушка component_epilog.php: частая причина «пропавших» данных в закешированном компоненте Битрикс

Павел Шулаев 10.08.2026
Хочу разобрать одну проблему, с которой рано или поздно сталкивается почти каждый, кто пишет свои шаблоны для компонентов Битрикс — и которая при этом почти не описана в документации. Ситуация типовая: на детальной странице (например, news.detail) нужно вывести что-то динамическое в component_epilog.php — мета-описание, JSON-LD, хлебные крошки с датой. Берём поле элемента, которое честно запросили через FIELD_CODE, оборачиваем в нужную обработку:
// component_epilog.php
$date = new \Bitrix\Main\Type\DateTime($arResult['ACTIVE_FROM']);
echo $date->format('d.m.Y'); // ожидаем дату публикации
И вот тут начинается странное: вместо реальной даты публикации на странице упорно висит сегодняшнее число. Причём не дата последней правки — именно "прямо сейчас". Обновляешь страницу — снова сегодня. Первая реакция почти у всех одинаковая — заподозрить что-то в инфраструктуре. Может, DateTime не смог распарсить формат даты без явной маски? Нет, парсит нормально. Может, дело в opcache — правишь файл, а сервер как будто отдаёт старую версию? Сбрасываешь opcache_reset() — не помогает. Может, виноват файловый кеш Битрикса — чистишь /bitrix/cache/ целиком — не помогает. Может, включён Composite-режим, и PHP вообще не выполняется, а отдаётся статический снепшот? Проверяешь — выключен. На этом этапе стандартный набор подозреваемых заканчивается, а проблема — нет. Дальше стоит спросить сам компонент напрямую: что вообще лежит в $arResult в этой конкретной точке выполнения.
// component_epilog.php
echo '<!-- ' . var_export(array_keys($arResult), true) . ' -->';
И тут вскрывается суть: в выводе — десяток ключей вроде ID, NAME, TIMESTAMP_X, IBLOCK — и ни следа от ACTIVE_FROM, хотя оно честно указано в FIELD_CODE. При этом в template.php того же самого компонента то же самое поле прекрасно доступно. Один файл видит полный набор данных, другой — заметно урезанный. Причина — в механике кеширования компонентов. HTML, который рисует template.php, целиком попадает в кеш — в этом весь смысл кеширования, не ходить в базу повторно. А component_epilog.php — это код, который обязан отработать каждый раз, даже когда страница отдаётся из кеша: он расставляет title, хлебные крошки, мета-теги — то, что нельзя просто зашить в статический HTML. Чтобы поведение не менялось между "посчитали заново" и "достали из кеша", Битрикс всегда прогоняет epilog с одним и тем же, заранее урезанным $arResult — тем набором полей, которые компонент сам явно объявил "безопасными для кеша". По умолчанию ACTIVE_FROM в этот список не входит — как и большинство полей, которые вы сами добавляли через FIELD_CODE. Чинится это не в epilog, а в result_modifier.php — там $arResult ещё полный, без урезаний. Нужное значение кладём в свой ключ и явно говорим компоненту сохранить его тоже:
// result_modifier.php
$this->__component->SetResultCacheKeys(['ACTIVE_FROM']);
// component_epilog.php
$date = new \Bitrix\Main\Type\DateTime($arResult['ACTIVE_FROM']);
echo $date->format('d.m.Y'); // теперь настоящая дата
Никакой магии — просто нужно было спросить сам компонент, а не подозревать инфраструктуру. Правило простое: если в component_epilog.php какого-то поля "почему-то нет", хотя оно точно запрошено через FIELD_CODE — это не сбой сервера и не кривой деплой. Компонент показывает там не тот $arResult, что в шаблоне, а его кешируемое подмножество. Нужное значение стоит явно "прокидывать" через result_modifier.php и SetResultCacheKeys() — а opcache, скорее всего, ни при чём, хоть и первый на подозрении почти всегда.

Битрикс api кеш

← Все статьи блога

  • Комментарии
Загрузка комментариев...