Свой компонент - структура, параметры, кэш результата
Пишем свой компонент: разбираем обязательные файлы, параметры и кэширование, из-за которого чаще всего и заводят компонент вместо кода в шаблоне страницы.
Решение
Собираем каталог компонента:
/home/bitrix/www/local/components/vendor/last.orders/├── class.php # логика: получение и подготовка данных├── .parameters.php # описание параметров для интерфейса├── .description.php # имя и раздел в списке компонентов└── templates/.default/template.php # разметкаКомпонент - это каталог с заранее известным платформе набором файлов. Логика живёт в классе, а разметка в шаблоне. Именно это разделение позволяет менять внешний вид, вообще не трогая получение данных.
Описываем параметры:
$arComponentParameters = ['PARAMETERS' => [ 'COUNT' => ['NAME' => 'Сколько показывать', 'TYPE' => 'STRING', 'DEFAULT' => '5'], 'CACHE_TIME' => ['DEFAULT' => 3600],]];// без значения по умолчанию компонент падает сразу после вставки на страницуПараметры описывают ровно то, что настраивается через обычный интерфейс страницы. Значение по умолчанию здесь не формальность: компонент, вставленный без настройки, должен работать, а не падать на пустом параметре.
Кэшируем результат с правильным ключом:
if ($this->startResultCache(false, [$USER->GetUserGroupArray(), $this->arParams['COUNT']])) { $this->arResult['ITEMS'] = $this->loadOrders(); // всё дорогое внутри $this->includeComponentTemplate();}В ключ кэша входят все значимые параметры и права текущего посетителя. Забытая группа пользователя - это чужие данные в кэше. Проявляется она обычно не сразу, а через жалобу «вижу не свои заказы».
Отдаём разметку шаблону:
foreach ($arResult['ITEMS'] as $item): ?> <div class="order"><?= htmlspecialcharsbx($item['NAME']) ?></div><?php endforeach;// запросов к базе в шаблоне быть не должно: они выполняются мимо кэша// в ключ кэша попадают группы пользователя: иначе чужие данные уедут всемЗапрос к базе прямо в шаблоне выполняется мимо кэша компонента. Именно поэтому кэшированный компонент иногда не даёт ускорения: дорогая часть переехала в шаблон и считается на каждом показе.
Свой компонент оправдан только там, где меняется сама логика получения этих данных. Если нужен другой внешний вид, дешевле сделать свой шаблон штатного компонента и не поддерживать лишний код.
Логику стоит держать в классе своего модуля, а сам компонент оставлять тонким. Тогда её можно вызвать из агента, из обработчика и из другого компонента, а не копировать между тремя похожими каталогами.
Копию штатного компонента заводят только под новым собственным именем каталога. Правка компонента в каталоге платформы возвращается к исходному виду при первом же обновлении, и вместе с ней возвращается исходное поведение сайта.
Отладку компонента начинают с отключённого кэша и с включённой панели отладки страницы. Иначе половина правок не доходит до страницы, а вторая половина выглядит работающей ровно до сброса кэша.
Типичные проблемы
Посетители видят чужие данные.
В ключ кэша не вошли группы текущего пользователя сайта. Кэш собран первым зашедшим гостем и отдаётся дальше всем подряд.
Кэш включён, а быстрее не стало.
Дорогие запросы к базе выполняются прямо в шаблоне компонента. Шаблон компонента отрабатывает и при попадании в готовый кэш точно так же.
После обновления платформы правки пропали.
Правился штатный компонент платформы вместо собственной копии. Обновление возвращает все файлы платформы к исходному виду.
Компонент падает без настроек.
У параметров этого компонента нет значений по умолчанию. Вставленный без всякой настройки компонент обязан работать.
Правки не видны при отладке.
Компонент отдаёт уже готовый результат из своего кэша. На время правок кэширование этого компонента отключают.
Частые вопросы
Чем свой компонент лучше кода в шаблоне страницы?
Он переиспользуется, кэшируется и настраивается параметрами. Код в шаблоне страницы не даёт ничего из этого.
Где хранить свои компоненты?
В своём пространстве имён внутри каталога проекта. Каталог штатных компонентов обновление перезапишет.
Нужен ли компоненту класс?
На новых проектах - да: класс удобнее для наследования и тестирования. Старый формат с одним файлом тоже работает.
Как передать данные из компонента в шаблон?
Через массив результата: он и есть договор между ними. Прямое обращение к своим методам из шаблона ломает кэширование.
Смежное
- Компонент изнутри: вызов, кэш, шаблон, эпилог - что происходит при вызове компонента
- Свой компонент - оглавление подтемы
- AJAX-действия своего компонента: действия, параметры, ошибки - как компонент принимает запросы
- Свой компонент не подключается: разбор причин - если вывода нет совсем
- Компоненты 2.0 - устройство компонентов целиком
- Стили и скрипты в шаблоне: подключение, порядок, кэш - обвязка страницы вокруг компонентов
- Кэширование своей выборки: ключ, теги, сброс - тот же механизм вне компонентов
- Свой модуль: структура, установка, автозагрузка - где живёт остальная логика решения
- Шаблон чужого компонента: копия, доработка результата, эпилог - когда своего компонента не нужно
- Языковые файлы: сообщения, подстановки, второй язык - тексты кода, параметров и шаблона
- Наследование чужого компонента: расширить, не копируя - когда чужой почти подходит