Как настроить result_modifier и component_epilog в шаблоне 1С-Битрикс?

В реальном проекте типичная ошибка такая: заголовок страницы верный на первом заходе, а со второго - старый. Вы перенесли SetTitle в template.php, потом в component_epilog.php, но $arResult['NAME'] там пустой - SetTitle в epilog не работает, пока ключ не зарегистрирован. Причина в кеше шаблона: при CACHE_TYPE=A ядро не вызывает result_modifier и template на каждом хите, а в epilog отдаёт только ключи из SetResultCacheKeys. Ниже разложим цепочку result_modifier → template.php → component_epilog и соберём рабочий паттерн для SetPageProperty на каждом запросе.

Шаблон компонента - это не только template.php. result_modifier.php готовит $arResult и кешируется вместе с HTML шаблона. component_epilog.php выполняется на каждом хите, но видит урезанный $arResult: только поля, зарегистрированные через SetResultCacheKeys в modifier. SetTitle и SetPageProperty для SEO переносите в epilog, а нужные ключи заранее сохраняйте в кеш.

Речь про 1С-Битрикс: Управление сайтом (коробочная CMS на своём хостинге), а не про облачный Bitrix24. Шаблон компонента лежит в /local/templates/имя_шаблона_сайта/components/vendor/компонент/шаблон/ - копируете системный шаблон из /bitrix/components/, правите только в local. Форму настроек в редакторе описывает .parameters.php, каркас компонента - class.php и /local/components. Здесь фокус на трёх файлах внутри папки шаблона.

Разберите порядок выполнения: component.php → result_modifier → template → epilog

Таблица: что кешируется на каждом этапе шаблона компонента Битрикс

Когда на странице вызывается $APPLICATION->IncludeComponent(), ядро проходит цепочку. Представьте конвейер: сначала собирают детали, потом красят корпус, в конце вешают бирку с ценой на витрине.

Схема на CMS:
component.php или class.php (startResultCache, сбор $arResult) → result_modifier.php (дополняет $arResult) → template.php (HTML) → component_epilog.php (пост-действия на каждом хите)

При валидном кеше шаблона (CACHE_TYPE=A) ядро подставляет готовый HTML и пропускает result_modifier и template.php. component_epilog.php вызывается всегда. Отсюда главное правило: всё, что должно меняться на каждом запросе (заголовок, мета, счётчик просмотров), держите в epilog, а данные для него заранее положите в кеш через SetResultCacheKeys.

Файл шаблона Когда выполняется Кешируется при CACHE_TYPE=A Типичная задача
result_modifier.php До template.php, после component.php Да, вместе с шаблоном Фильтры, группировка, вычисленные поля для верстки
template.php После modifier Да (HTML-кеш) Вывод разметки из $arResult
component_epilog.php После template (или после HTML из кеша) Нет, на каждом хите SetTitle, SetPageProperty, addExternalCss/JS

Делайте: тяжёлую логику переносите из template.php в result_modifier - так проще тестировать и не смешивать PHP с вёрсткой. Не делайте: не вызывайте SetTitle в template.php, если включён автокеш - заголовок "застынет" после первого хита.

Настройте result_modifier.php: подготовка $arResult и сброс кеша после правок

Схема workflow: правка result_modifier, сброс кеша и проверка $arResult

Официальный урок по result_modifier.php фиксирует: файл вызывается перед template.php и может менять $arResult. На практике часто ломается так: вы правите modifier, обновляете страницу - изменений нет. Это не баг ядра, а закешированный шаблон; правки result_modifier «не видны», пока не сбросите кеш.

  1. Откройте папку шаблона в /local/templates/…/components/bitrix/news.detail/your_template/.
  2. Создайте или отредактируйте result_modifier.php: вынесите сюда расчёт дат, склонений, флагов "показать баннер".
  3. Синхронизируйте локальный $arResult с объектом компонента: $cp = $this->__component;.
  4. После правок сбросьте кеш: добавьте к URL ?clear_cache=Y или очистите кеш компонента в админке (подробнее в гайде по очистке кеша).
  5. Проверьте страницу в режиме инкогнито - без авторизации админа кеш иногда ведёт себя иначе.
  6. Если данные меняются при Update элемента, свяжите сброс с тегированным кешем - не полагайтесь только на CACHE_TIME.

Минимальный modifier для детальной новости:

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

$arResult['DISPLAY_DATE'] = FormatDate('j F Y', MakeTimeStamp($arResult['ACTIVE_FROM']));

Делайте: держите modifier идемпотентным - один и тот же вход $arResult даёт тот же выход. Не делайте: не пишите SetPageProperty в modifier и не ждите, что title обновится на каждом хите.

Зарегистрируйте ключи через SetResultCacheKeys для epilog при CACHE_TYPE=A

Чеклист: SetResultCacheKeys, epilog SetTitle и сброс кеша при CACHE_TYPE=A

Метод SetResultCacheKeys говорит ядру, какие поля $arResult сохранить в data-кеше и отдать в component_epilog.php при следующих хитах. Без регистрации epilog получит пустой или урезанный массив - отсюда миф "в epilog нет данных".

Рабочий паттерн из документации API: вызовы добавляют ключи, а не заменяют весь список. Регистрируйте только то, что нужно epilog - не весь $arResult, иначе файл в /bitrix/cache/ раздуется.

$cp = $this->__component;

$cp->arResult['SEO_TITLE'] = $arResult['NAME'];
$cp->arResult['SEO_DESCRIPTION'] = $arResult['PREVIEW_TEXT'];
$cp->SetResultCacheKeys(['SEO_TITLE', 'SEO_DESCRIPTION']);

$arResult['SEO_TITLE'] = $cp->arResult['SEO_TITLE'];
$arResult['SEO_DESCRIPTION'] = $cp->arResult['SEO_DESCRIPTION'];

Цепочка: modifier пишет в $cp->arResult → SetResultCacheKeys → те же ключи копируете в локальный $arResult для template.php. В epilog читаете $arResult['SEO_TITLE'] уже из кеша.

Делайте: перечисляйте 3-7 коротких скалярных полей (строки, ID, флаги). Не делайте: не кладите в кеш большие массивы ITEMS целиком "на всякий случай" - это бьёт по скорости чтения кеша.

Настройте component_epilog.php: SetTitle и SetPageProperty на каждом хите

component_epilog.php появился в ядре с версии 9.0 и решает задачу "HTML уже из кеша, а мета должна быть свежей". Официальный курс прямо предупреждает: $APPLICATION->SetTitle() в result_modifier сработает только пока шаблон не закеширован.

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

global $APPLICATION;

if (!empty($arResult['SEO_TITLE'])) {
    $APPLICATION->SetTitle($arResult['SEO_TITLE']);
}
if (!empty($arResult['SEO_DESCRIPTION'])) {
    $APPLICATION->SetPageProperty('description', $arResult['SEO_DESCRIPTION']);
}

Сюда же можно подключить CSS/JS через $this->addExternalCss() и $this->addExternalJS(), если файл должен грузиться при каждом показе компонента. Счётчики и A/B-флаги тоже логичнее в epilog, а не в template.php.

Альтернатива для данных из template в epilog - templateData (массив шаблона), но для SEO-полей из component.php надёжнее SetResultCacheKeys в modifier: template при кеше не выполняется.

Делайте: проверяйте epilog с двумя подряд обновлениями страницы без clear_cache - title должен совпадать с элементом. Не делайте: не дублируйте SetTitle и в template, и в epilog - останется только первый сработавший при промахе кеша.

Пройдите чек-лист отладки: кеш, epilog и заголовок страницы

Когда "всё сделали по гайду", а заголовок пустой, идите по списку сверху вниз.

  1. Убедитесь, что в шаблоне компонента CACHE_TYPE не N, если тестируете кеш (A - авто, Y - всегда).
  2. В result_modifier вызван SetResultCacheKeys с теми же ключами, что читаете в epilog.
  3. После правок modifier или template сбросьте кеш: ?clear_cache=Y или $component->clearResultCache() при программном обновлении.
  4. Откройте файл кеша в /bitrix/cache/ - если он больше 1 МБ, урежьте ключи (рекомендация из документации по производительности инфоблоков).
  5. Проверьте, что epilog лежит в той же папке шаблона, что и template.php, а не в соседнем .default.
  6. Свяжите инвалидацию с тегами iblock_id_N, если контент меняется из админки без деплоя.

Workflow отладки: правка modifier → clear_cache → первый хит (сбор кеша) → второй хит (epilog + урезанный $arResult) → сравнение title в инкогнито.

Если после чек-листа остаются вопросы по слоям кеша сайта (composite, managed), вернитесь к пошаговой очистке кеша. Нужна помощь с внедрением на боевом проекте - обсудим задачу.

Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: урок "Шаблоны компонента", урок "result_modifier.php", API SetResultCacheKeys, рекомендации по размеру кеша.

Частые вопросы

Чем result_modifier.php отличается от component_epilog.php?

result_modifier готовит $arResult до верстки и кешируется вместе с шаблоном. component_epilog выполняется на каждом хите после вывода HTML и подходит для SetTitle, SetPageProperty и подключения скриптов. Логику вычислений держите в modifier, пост-действия - в epilog.

Зачем нужен SetResultCacheKeys?

При CACHE_TYPE=A ядро не вызывает modifier на каждом запросе, а в epilog передаёт только ключи, которые вы зарегистрировали через SetResultCacheKeys в result_modifier. Без этого вызова $arResult в epilog будет пустым или без нужных полей.

Почему в component_epilog пустой $arResult?

Вы не вызвали SetResultCacheKeys для нужных ключей или читаете поля, которых нет в data-кеше. Добавьте регистрацию в result_modifier, сбросьте кеш компонента и проверьте второй хит без clear_cache.

Кешируется ли result_modifier.php?

Да. При валидном кеше шаблона modifier и template.php пропускаются, выполняется только component_epilog с урезанным $arResult. Поэтому правки modifier не видны, пока не сбросите кеш.

Можно ли вызывать SetTitle в template.php?

Можно только если кеш шаблона отключён (CACHE_TYPE=N). При автокеше template не выполняется на повторных хитах, и заголовок останется от первого запроса. Для стабильного SEO перенесите SetTitle в component_epilog и передайте данные через SetResultCacheKeys.

Где вызывать SetResultCacheKeys - в component.php или в modifier?

Чаще в result_modifier.php: там вы уже готовите поля для шаблона и epilog. В class.php метод тоже допустим внутри startResultCache перед endResultCache, если ключи формируются на уровне компонента, а не шаблона.

Обсудить вашу задачу

Было полезно?

Поставьте лайк, если статья помогла разобраться.

Поделиться статьёй

Отправьте тому, кому это пригодится.

Telegram ↗ MAX ↗ ВКонтакте ↗ Одноклассники ↗
Все статьи ↗

Как настроить регистрацию и личный кабинет покупателя на 1С-Битрикс?

Структура шаблонов сайта в Битриксе и поиск header footer

Как настроить скидки и промокоды на 1С-Битрикс: правила корзины и купоны