Файл component_epilog.php
При использовании компонента в Битриксе часто нужно, чтобы компонент не только выводил данные на страницу, но и выполнял некоторые дополнительные действия: изменение заголовка страницы, добавление элементов навигационной цепочки и т. п. Раньше (при работе с версией Битрикса, младшей чем 9.0) для реализации такого поведения необходимо было модифицировать основной файл компонента component.php
.
В версии 9.0 в шаблон компонента был добавлен файл component_epilog.php — эпилог компонента. Его особенность в том, что он, в отличие от файлов template.php
и result_modifier.php
, исполняется при каждом вызове компонента, вне зависимости от наличия кеша. Кроме того, в component_epilog.php
доступны привычные массивы $arParams
и $arResult
.
Как работает компонент
Для начала небольшое описание составных частей среднестатистического компонента в Битрикс:
component.php
файл с кодом, который формирует данные для шаблона (массив$arResult
) и подключает шаблон. Кроме того, может выполнять какие-либо действия после получения данных. Например, устанавливать заголовок страницы или добавлять пункты в навигационную цепочкуtemplate.php
файл шаблона. В идеале не содержит никакой логики, только вывод данных из$arResult
. Кешируется html-вывод, т.е. PHP код из этого файла выполнится один раз, затем будет возвращаться html до следующего обновления кешаresult_modifier.php
файл, который подключается доtemplate.php
и может менять$arResult
. Кешируется так же, как иtemplate.php
component_epilog.php
файл, который подключается послеtemplate.php
, никогда не кешируется
Последние три файла относятся к шаблону, предпочтительно редактировать именно их. Файл component.php
в стандартных компонентах изменять нельзя, т.к. есть шанс, что правки затрутся после обновления системы.
Общую схему работы компонента можно представить несколькими шагами:
- Проверка входных данных в
component.php
- Проверка на наличие валидного (активного) кеша файлов
result_modifier.php
иtemplate.php
. Если кеш валидный, то вывод html, воссоздание массива$arResult
с ключами из вызоваSetResultCacheKeys()
и переход к пункту 5 - В случае невалидного кеша производятся необходимые действия для получения данных, т.е. заполнение массива
$arResult
- Подключение файлов
result_modifier.php
иtemplate.php
, формирование + вывод html, а также сохранение в кеше вывода и части массива$arResult
- Подключение файла
component_epilog.php
- Выполнение остального кода в
component.php
Что нужно помнить
Содержимое массива $arResult
на разных этапах различается. В result_modifier.php
и template.php
попадает массив, содержащий все данные, которые получены на третьем шаге. В файле component_epilog.php
и коде компонента, который выполняется после него, доступны данные массива $arResult
с ключами, которые были указаны в функции SetResultCacheKeys()
. Вызов ее происходит в component.php
.
/*
* Подготовка входных параметров компонента
*/
// время кеширования
if (!isset($arParams['CACHE_TIME'])) {
$arParams['CACHE_TIME'] = 3600;
} else {
$arParams['CACHE_TIME'] = intval($arParams['CACHE_TIME']);
}
// идентификатор элемента инфоблока
$arParams['ELEMENT_ID'] = empty($arParams['ELEMENT_ID']) ? 0 : intval($arParams['ELEMENT_ID']);
/*
* Типичный алгоритм кеширования
*/
if ($this->StartResultCache()) {
/*
* Если нет валидного кеша — получаем данные из БД
*/
if ( ! \Bitrix\Main\Loader::includeModule('iblock')) {
$this->AbortResultCache();
ShowError('Модуль «Информационные блоки» не установлен');
return;
}
if ($arParams['ELEMENT_ID']) {
// выполняем запрос к базе данных
$rsElement = CIBlockElement::GetList(/*...*/);
if ($arResult = $rsElement->GetNext()) {
/*
* Добавляем в массив arResult дополнительные элементы,
* которые могут потребоваться в шаблоне
*/
}
}
if (isset($arResult['ID'])) { // данные получены успешно
/*
* Ключи $arResult, перечисленные при вызове этого метода,
* будут доступны в component_epilog.php и ниже по коду;
* обратите внимание, там уже будет другой $arResult
*/
$this->SetResultCacheKeys(
array(
'ID',
'NAME'
)
);
// подключаем шаблон и сохраняем кеш
$this->IncludeComponentTemplate();
} else { // что-то пошло не так
$this->AbortResultCache();
\Bitrix\Iblock\Component\Tools::process404(
'Страница не найдена',
true,
true
);
}
}
/*
* Кэш не затронет весь код ниже, он будут выполняться на каждом хите, но
* здесь работаем уже с другим $arResult — будут доступны только те ключи
* массива, которые перечислены в вызове SetResultCacheKeys()
*/
if (isset($arResult['ID'])) {
// счетчик просмотров элемента
CIBlockElement::CounterInc($arResult['ID']);
// устанавливаем заголовок страницы
$APPLICATION->SetTitle($arResult['NAME']);
}
Например, нам нужно вывести заголовок страницы вида «[Название инфоблока] (кол-во элементов)»:
/*
* Фрагмент кода из файла component.php, где устанавливаются ключи, которые попадут в кеш
*/
$this->SetResultCacheKeys(
array(
"ID",
"IBLOCK_TYPE_ID",
"LIST_PAGE_URL",
"NAV_CACHED_DATA",
"NAME",
"SECTION",
"ELEMENTS",
)
);
/*
* Фрагмент кода из файла component_epilog.php, где устанавливается заголовок страницы
*/
global $APPLICATION;
// этот код не сработает, т.к. в массиве $arResult не определен элемент с ключом «ITEMS»
if (isset($arResult['NAME']) && isset($arResult['ITEMS'])) {
$title = $arResult['NAME'] . ' (' . count($arResult['ITEMS']) . ')';
$APPLICATION->SetTitle($title);
}
// правильный вариант, все нужные элемента массива присутствуют в кеше
if (isset($arResult['NAME']) && isset($arResult['ELEMENTS'])) {
$title = $arResult['NAME'] . ' (' . count($arResult['ELEMENTS']) . ')';
$APPLICATION->SetTitle($title);
}
Данные, которые доступны в component_epilog.php
и далее (т.е. указаны в вызове SetResultCacheKeys()
) можно изменять в result_modifier.php
и template.php
. Будет закешировано их новое значение.
/*
* Фрагмент кода из файла result_modifier.php шаблона компонента news.list. Задача — вывести
* заголовок страницы вида «[Название инфоблока] (кол-во элементов)»
*/
// доступен весь массив $arResult и мы можем переопределить элементы, которые попадут в кеш
$arResult['NAME'] .= ' (' . count($arResult['ELEMENTS']) . ')';
/*
* Фрагмент кода из файла component_epilog.php, где устанавливается заголовок страницы
*/
global $APPLICATION;
// компонент использует измененный $arResult['NAME'] и мы получим нужный заголовок
if (isset($arResult['NAME'])) {
$APPLICATION->SetTitle($arResult['NAME']);
}
В result_modifier.php
можно добавлять данные в кеш.
/*
* Фрагмент кода из файла result_modifier.php шаблона компонента news.list. Задача — сделать мета-тег
* description вида «[Названия элементов через запятую] скачать бесплатно без регистрации»
*/
$arNames = array(); // сюда собираем названия элементов
foreach ($arResult['ITEMS'] as $arItem) {
$arNames[] = $arItem['NAME'];
}
$arResult['DESCRIPTION'] = implode(', ', $arNames) . ' скачать бесплатно без регистрации';
$cp = $this->__component; // объект компонента
if (is_object($cp)) {
$cp->SetResultCacheKeys(array('DESCRIPTION')); // запомнить $arResult['DESCRIPTION'] в кеш
}
/*
* Фрагмент кода из файла component_epilog.php, где устанавливается мета-тег description
*/
global $APPLICATION;
// устанавливаем свойство DESCRIPTION
if (isset($arResult['DESCRIPTION'])) {
$APPLICATION->SetDirProperty('description', $arResult['DESCRIPTION']);
}