В реальном проекте типичная ошибка такая: заголовок страницы верный на первом заходе, а со второго - старый. Вы перенесли 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 и сброс кеша после правок
Официальный урок по result_modifier.php фиксирует: файл вызывается перед template.php и может менять $arResult. На практике часто ломается так: вы правите modifier, обновляете страницу - изменений нет. Это не баг ядра, а закешированный шаблон; правки result_modifier «не видны», пока не сбросите кеш.
- Откройте папку шаблона в
/local/templates/…/components/bitrix/news.detail/your_template/. - Создайте или отредактируйте
result_modifier.php: вынесите сюда расчёт дат, склонений, флагов "показать баннер". - Синхронизируйте локальный
$arResultс объектом компонента:$cp = $this->__component;. - После правок сбросьте кеш: добавьте к URL
?clear_cache=Yили очистите кеш компонента в админке (подробнее в гайде по очистке кеша). - Проверьте страницу в режиме инкогнито - без авторизации админа кеш иногда ведёт себя иначе.
- Если данные меняются при 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 говорит ядру, какие поля $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 и заголовок страницы
Когда "всё сделали по гайду", а заголовок пустой, идите по списку сверху вниз.
- Убедитесь, что в шаблоне компонента
CACHE_TYPEне N, если тестируете кеш (A - авто, Y - всегда). - В result_modifier вызван
SetResultCacheKeysс теми же ключами, что читаете в epilog. - После правок modifier или template сбросьте кеш:
?clear_cache=Yили$component->clearResultCache()при программном обновлении. - Откройте файл кеша в
/bitrix/cache/- если он больше 1 МБ, урежьте ключи (рекомендация из документации по производительности инфоблоков). - Проверьте, что epilog лежит в той же папке шаблона, что и template.php, а не в соседнем .default.
- Свяжите инвалидацию с тегами 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, если ключи формируются на уровне компонента, а не шаблона.
Было полезно?
Поставьте лайк, если статья помогла разобраться.
Поделиться статьёй
Отправьте тому, кому это пригодится.
Можно поделиться и фрагментом: выделите текст статьи.