6

Битрикс-разработка: особенности использования эпилога компонента

Дмитрий Кораблинов
24 февраля 2011 года

Для чего компоненту эпилог?

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

В качестве резюме: эпилог компонента — очень полезная штука, но следует помнить о его особенностях. Возможно, в следующих версиях Битрикса поведение эпилога будет все же доработано для более простого и очевидного использования.

Метки: , ,

6 комментариев к записи «Битрикс-разработка: особенности использования эпилога компонента»

  1. Алексей Валеев,

    Спасибо, про $templateData очень и очень полезная информация! И как всегда приходится лезть в ядро, чтобы эти возможности отыскать..

  2. Itachi261092,

    У меня данная фича не совсем сработала.
    $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 сохраняется что то не в глобальной переменной. но опять же — зачем?

  3. Itachi261092,

    прошу прощения за ошибки в тексте.
    1)$templateData позволяет передать в эпилог любые поля а не только стандартные.
    2)в компоненте SETTITLE срабатывает позже чем в шаблоне.

  4. Itachi261092, спасибо за отзыв.

    Что касается установки заголовка страницы, то многие стандартные компоненты вызывают метод SetTitle() после подключения шаблона компонента, а значит, после выполнения эпилога. Так что ваш способ имеет право на существование, хотя лично я в описанной ситуации отключил бы установку заголовка в параметрах компонента.

    Вызов SetResultCacheKeys(array()) зачастую не оправдан, так как в этом случае весь массив $arResult помещается в кеш, и размер кеша очень серьезно раздувается.

    Кстати, в учебных курсах Битрикса описан еще один способ проброса данных в эпилог c использованием объекта компонента, который стал доступен в последних версиях CMS.

  5. Роман,

    Дмитрий!

    Спасибо за материал, полезный для не особо опытных разработчиков. Внесу некоторые дополнения насчет использования Языковых файлов в эпилоге:

    Лучше не вписывать все языковые фразы в lang/ru/template.php, а лучше отдельно создать файл lang/ru/component_epilog.php и вручную подключить. Файл шаблона компонента может и совсем отсутствовать.

  6. Антон,

    По поводу 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»);
    В таком случае все будет работать и в кэше и мимо кэша.

Ответить на сообщение Itachi261092