Битрикс. Файл component_epilog.php

29.06.2018

Теги: $arParams$arResultCMScomponent_epilog.phpresult_modifier.phpWeb-разработкаБитриксКешированиеКомпонентШаблонКомпонента

При использовании компонента в Битриксе часто нужно, чтобы компонент не только выводил данные на страницу, но и выполнял некоторые дополнительные действия: изменение заголовка страницы, добавление элементов навигационной цепочки и т. п. Раньше (при работе с версией Битрикса, младшей чем 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 в стандартных компонентах изменять нельзя, т.к. есть шанс, что правки затрутся после обновления системы.

Общую схему работы компонента можно представить несколькими шагами:

  1. Проверка входных данных в component.php.
  2. Проверка на наличие валидного (активного) кеша файлов result_modifier.php и template.php. Если кеш валидный, то вывод html, воссоздание массива $arResult с ключами из вызова SetResultCacheKeys() и переход к пункту 5.
  3. В случае невалидного кеша производятся необходимые действия для получения данных, т.е. заполнение массива $arResult.
  4. Подключение файлов result_modifier.php и template.php, формирование + вывод html, а также сохранение в кеше вывода и части массива $arResult.
  5. Подключение файла component_epilog.php.
  6. Выполнение остального кода в 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']);
}

Поиск: $arParams • $arResult • CMS • Web-разработка • Битрикс • Компонент • Кеширование • Шаблон компонента • result_modifier.php • component_epilog.php • SetResultCacheKeys

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.