Для чего компоненту эпилог?
При использовании компонента в Битриксе часто нужно, чтобы компонент не только выводил данные на страницу, но и выполнял некоторые дополнительные действия: изменение заголовка страницы, добавление элементов навигационной цепочки и т. п. Раньше (при работе с версией Битрикса, младшей чем 9.0) для реализации такого поведения необходимо было модифицировать основной файл компонента (component.php
).
В версии 9.0 в шаблон компонента был добавлен файл component_epilog.php
— эпилог компонента. Его особенность в том, что он, в отличие от файлов template.php
и result_modifier.php
, исполняется при каждом вызове компонента, вне зависимости от наличия кеша. Кроме того, в component_epilog.php
доступны привычные массивы $arParams
и $arResult
. В теории это означает, что все дополнительные действия можно выполнить в эпилоге, что заметно упрощает жизнь разработчику.
Эпилог и кеширование
Но, как обычно, теория с практикой немного расходятся. Если с $arParams
проблем не возникает (так как по сути это предопределенный массив, который просто «пробрасывается» по всем файлам компонента), то c $arResult
есть некоторые нюансы.
Поскольку эпилог вызывается всегда, в том числе при использовании кеша компонента, то и $arResult
извлекается из кеша. Но многие компоненты кешируют не весь массив результата, а только некоторое его подмножество. Список ключей $arResult
, значения которых необходимо закешировать, определяется вызовом метода SetResultCacheKeys()
в файле component.php
. Следовательно, в эпилоге будут доступны ключи $arResult
только из этого списка.
Впрочем, данную проблему легко обойти. Достаточно в файле template.php
выполнить вызов
$component->SetResultCacheKeys(array("key1", "key2", ...));
где key1
и key2
— ключи $arResult
, которых не хватает в кеше. После такого вызова нужные данные попадут в кеш и будут доступны в файле эпилога.
Эпилог и модификатор результата
Более интересная ситуация возникает, когда содержимое $arResult
изменяется в файле модификатора — result_modifier.php
. Никакие изменения, выполненные в модификаторе, не видны в эпилоге. Причина такого поведения проста: в кеш записывается то состояние $arResult
, которое имеется перед подключением шаблона компонента, а значит, до выполнения модификатора. Это уже накладывает серьезное ограничение на использование component_epilog.php
.
После очередного «увлекательного путешествия» по коду ядра Битрикса решение проблемы было найдено. Но сразу оговорюсь, что описываемое далее решение официально не документировано, поэтому пользоваться им надо с осторожностью.
Как оказалось, помимо $arResult
и $arParams
инфраструктура компонентов Битрикса предоставляет еще один предопределенный массив — $templateData
. Этот массив объявляется перед выполнением template.php
(но после выполнения result_modifier.php
, так что использовать его в модификаторе нельзя). А примечателен он тем, что кешируется вместе с $arResult
и доступен в эпилоге компонета! Следовательно, если $arResult
был изменен в модификаторе, и измененные данные необходимо использовать в эпилоге, то нужно в файле template.php
записать измененные данные в массив $templateData
. Следующий пример кода наглядно демострирует такой подход:
result_modifier.php
...
$arResult['CUSTOM_TITLE'] = 'Custom page title';
...
template.php
...
$templateData['CUSTOM_TITLE'] = $arResult['CUSTOM_TITLE'];
...
component_epilog.php
...
global $APPLICATION;
$APPLICATION->SetTitle($templateData['CUSTOM_TITLE']);
...
Эпилог и языковые файлы
Еще одна особенность эпилога — это работа с языковыми файлами. Языковые константы для эпилога должны располагаться не в файле lang/ru/component_epilog.php
, как можно было бы ожидать, а в файле lang/ru/template.php
. Мелочь, но тоже может стоить разработчику немало нервных клеток.
В качестве резюме: эпилог компонента — очень полезная штука, но следует помнить о его особенностях. Возможно, в следующих версиях Битрикса поведение эпилога будет все же доработано для более простого и очевидного использования.
Метки: битрикс, программирование, создание сайтов
Спасибо, про $templateData очень и очень полезная информация! И как всегда приходится лезть в ядро, чтобы эти возможности отыскать..
У меня данная фича не совсем сработала.
$templateData действительно позволяет передать в эпилог все стандартные поля. Но только хоть при включённом кешировании, хоть при отключённом пытаться добавить в эпилоге шаблона любого простого компонента в составе сложного (пример: bitrix:news) $APPLICATION->SetTitle, то эта команда не срабатывает в случае если в вызове активен SET_TITLE. не копался сильно в логике компонента, но думаю его SetTemplate просто срабатывает на более позднем этапе и перебивает пользовательский результат.
Я решил проблему намного проще. в эпилоге выводится строка:
$component->arResult[‘NAME’] = ‘asd’ //внимание, строку не править — ошибок нет. приравнивать можно любые значения.
У меня задача стояла немного сложнее. есть имя $arResult[«NAME»] и не обязательное пользовательское поле раздела, например UF_USER_NAME. Если значение поля заполнено, устанавливать в заголовок это значение. иначе — просто имя. передал из шаблона UF_USER_NAME через $templateData, и сделал проверку по двум условиям (если set_title=Y и если это поле не пустое, приравниваем это поле к $arResult[‘NAME’], и потом выводим $component->arResult[‘NAME’] = $arResult[«NAME»]; — работает как часы.
Ещё одно замечание. Зачем использовать templateData, если $component->SetResultCacheKeys(array()); даже в закешированном виде передаёт всё отлично? могу предположить что это подойдёт только когда в result_modifier.php сохраняется что то не в глобальной переменной. но опять же — зачем?
прошу прощения за ошибки в тексте.
1)$templateData позволяет передать в эпилог любые поля а не только стандартные.
2)в компоненте SETTITLE срабатывает позже чем в шаблоне.
Itachi261092, спасибо за отзыв.
Что касается установки заголовка страницы, то многие стандартные компоненты вызывают метод SetTitle() после подключения шаблона компонента, а значит, после выполнения эпилога. Так что ваш способ имеет право на существование, хотя лично я в описанной ситуации отключил бы установку заголовка в параметрах компонента.
Вызов SetResultCacheKeys(array()) зачастую не оправдан, так как в этом случае весь массив $arResult помещается в кеш, и размер кеша очень серьезно раздувается.
Кстати, в учебных курсах Битрикса описан еще один способ проброса данных в эпилог c использованием объекта компонента, который стал доступен в последних версиях CMS.
Дмитрий!
Спасибо за материал, полезный для не особо опытных разработчиков. Внесу некоторые дополнения насчет использования Языковых файлов в эпилоге:
Лучше не вписывать все языковые фразы в lang/ru/template.php, а лучше отдельно создать файл lang/ru/component_epilog.php и вручную подключить. Файл шаблона компонента может и совсем отсутствовать.
По поводу lang/ru/component_epilog.php и lang/ru/template.php.
Если языковые фразы писать в template.php, то они будут выводиться только когда компонент работает мимо кэша. При работе кэширования языковые фразы потеряются.
Поэтому правильно сохранять фразы в lang/ru/component_epilog.php, а в самом файле эпилога прописать следующее:
use \Bitrix\Main\Localization\Loc;
Loc::loadLanguageFile(__FILE__);
echo Loc::getMessage(«SOMETHING_LANGUAGE_CONSTANT»);
В таком случае все будет работать и в кэше и мимо кэша.