Доопрацювання стандартних компонентів через component_epilog у 1С-Бітрікс
component_epilog.php — файл у папці шаблону компонента, який виконується після повного завершення роботи компонента, включно з рендером шаблону. На відміну від result_modifier.php, тут вже не можна вплинути на HTML-виведення поточного компонента — зате можна виконати код із побічними ефектами, не порушуючи логіку кешування.
Місце в послідовності виконання
1. component.php (логіка, заповнює $arResult)
2. result_modifier.php (модифікація $arResult, до рендеру)
3. template.php (рендер HTML)
4. component_epilog.php (після рендеру — дії, JS, аналітика)
Файл знаходиться в папці шаблону компонента:
/local/templates/{site_template}/components/bitrix/catalog.element/default/component_epilog.php
Чим component_epilog відрізняється від result_modifier
| result_modifier | component_epilog | |
|---|---|---|
| Коли виконується | До рендеру шаблону | Після рендеру шаблону |
Доступний $arResult |
Так, для зміни | Так, лише для читання |
| Впливає на HTML компонента | Так (через $arResult) |
Ні |
| Виконується при кеші | Ні (дані беруться з кешу) | Так, завжди |
| Для JS та аналітики | Ні | Так |
| Для побічних ефектів | Ні | Так |
Ключова відмінність: component_epilog.php виконується завжди, навіть коли компонент віддає результат із кешу. Це робить його ідеальним місцем для коду, який має працювати при кожному запиті — незалежно від стану кешу.
Практичні застосування
Виведення JS-даних для аналітики (GA4 / Яндекс.Метрика):
Дані товару для аналітики потрібні при кожному перегляді сторінки, навіть якщо компонент закешований:
// component_epilog.php для bitrix:catalog.element
if (!empty($arResult['ID'])) {
$price = $arResult['CATALOG_PRICE_1'] ?? 0;
$name = $arResult['NAME'] ?? '';
$category = $arResult['SECTION']['NAME'] ?? '';
$productJson = json_encode([
'id' => $arResult['ID'],
'name' => $name,
'price' => $price,
'category' => $category,
], JSON_UNESCAPED_UNICODE);
// Виводимо JS прямо з epilog — або додаємо в <head>
global $APPLICATION;
$APPLICATION->AddHeadScript('');
?>
<script>
window.pageProduct = <?= $productJson ?>;
gtag('event', 'view_item', {
currency: 'RUB',
value: <?= $price ?>,
items: [{ item_id: '<?= $arResult['ID'] ?>', item_name: <?= json_encode($name) ?>, price: <?= $price ?> }]
});
ym(METRIKA_ID, 'reachGoal', 'product_view', { product_id: <?= $arResult['ID'] ?> });
</script>
<?php
}
Реєстрація перегляду товару в системі аналітики:
Оновити лічильник переглядів у кастомній таблиці при кожному перегляді — не порушуючи кеш компонента:
// component_epilog.php для bitrix:catalog.element
if (!empty($arResult['ID'])) {
// Не виконуємо для ботів
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
if (preg_match('/bot|crawler|spider|crawling/i', $userAgent)) return;
// Інкрементуємо лічильник (без блокувальних запитів — через чергу)
ViewCounterQueue::increment($arResult['ID']);
}
ViewCounterQueue::increment() записує в Redis або кастомну таблицю — агент періодично скидає накопичені перегляди в основну таблицю пакетним UPDATE.
Пов'язані товари: доповнення після рендеру основного контенту:
Якщо блок «схожі товари» важкий і не має входити в кеш основного компонента:
// component_epilog.php для bitrix:catalog.element
if (!empty($arResult['ID'])) {
// Компонент із власним кешем — не залежить від кешу батьківського
$APPLICATION->IncludeComponent(
'bitrix:catalog.section',
'related_products',
[
'IBLOCK_ID' => $arResult['IBLOCK_ID'],
'FILTER_IDS' => getRelatedProductIds($arResult['ID']),
'CACHE_TYPE' => 'A',
'CACHE_TIME' => 3600,
]
);
}
Логування подій без блокування основного запиту:
// component_epilog.php для bitrix:sale.basket.basket
if (!empty($arResult['ITEMS'])) {
$basketValue = array_sum(array_column($arResult['ITEMS'], 'PRICE'));
// Пишемо в лог без очікування
register_shutdown_function(function() use ($basketValue) {
BasketAnalyticsLog::record([
'fuser_id' => \Bitrix\Sale\Fuser::getId(),
'basket_value' => $basketValue,
'items_count' => count($arResult['ITEMS']),
'timestamp' => time(),
]);
});
}
component_epilog і Ajax-компоненти
Стандартний компонент sale.order.ajax використовує AJAX для оновлення кроків оформлення. У цьому випадку component_epilog.php виконується при кожному AJAX-запиті, що може призвести до дублювання JS-коду на сторінці.
Перевіряйте, що запит не є AJAX:
// component_epilog.php
if (\Bitrix\Main\Context::getCurrent()->getRequest()->isAjaxRequest()) {
return; // не виводимо JS при AJAX-запитах
}
// Основний код epilog тут
Робота з $arResult в epilog
У component_epilog.php $arResult — це той самий масив, що був у result_modifier.php та template.php. Він доступний для читання, але зміни в ньому не впливають на вже виведений HTML. Зміни $arResult в epilog впливають лише на код, який ви самі виконуєте всередині epilog.
// component_epilog.php
// Це НЕ вплине на вже виведений template.php:
$arResult['NAME'] = 'Нова назва'; // марно
// Але можна використовувати $arResult для формування JS або API-запитів:
$analyticsData = [
'product_id' => $arResult['ID'],
'in_stock' => ($arResult['CATALOG_QUANTITY'] ?? 0) > 0,
];
Структура папки шаблону з обома файлами
/local/templates/main/components/bitrix/catalog.element/default/
template.php — HTML-шаблон
result_modifier.php — модифікація $arResult до рендеру
component_epilog.php — JS, аналітика, побічні ефекти після рендеру
.description.php — метадані шаблону (необов'язково)
style.css — стилі (необов'язково)
script.js — скрипти (необов'язково)
Обидва файли — доповнювальні інструменти: result_modifier.php для даних, component_epilog.php для дій. Разом вони дозволяють повністю кастомізувати поведінку стандартного компонента, не торкаючись його вихідного коду.
Склад робіт: написання component_epilog.php для конкретного компонента з аналітикою та побічними ефектами — 4–8 годин. З чергою переглядів та агентом — ще 1–2 дні.







