Налаштування кешування кастомних компонентів 1С-Бітрікс
Компонент без кешування — це запит до бази даних при кожному перегляді сторінки. При 1 000 переглядів на добу це 1 000 запитів; при 10 000 — вже реальне навантаження. Кешування у Бітрікс — не чарівна кнопка «увімкнути», це набір конкретних рішень: що кешувати, як довго, за яким ключем і як інвалідувати при зміні даних.
Механізм кешування Бітрікс
Бітрікс використовує файловий кеш за замовчуванням. Кеш зберігається в /bitrix/cache/ (або /upload/cache/ залежно від конфігурації). Кожен кеш-файл — серіалізований $arResult компонента. При попаданні в кеш template.php викликається з кешованими даними — жодних запитів до БД.
Два рівні кешування:
-
Кеш результату (
StartResultCache/EndResultCache) — кешується$arResult - Кеш HTML (composit-кеш, окремий механізм) — кешується підсумковий HTML
Для кастомних компонентів використовується перший рівень.
Базове використання StartResultCache
// component.php
$cacheId = serialize([
$arParams['IBLOCK_ID'],
$arParams['COUNT'],
$arParams['SECTION_ID'],
LANGUAGE_ID,
SITE_ID,
]);
$cacheDir = '/custom/my.component/' . $arParams['IBLOCK_ID'] . '/';
if ($this->StartResultCache($arParams['CACHE_TIME'], $cacheId, $cacheDir)) {
// Цей блок виконується тільки за відсутності кешу
$this->arResult = $this->getData();
$this->IncludeComponentTemplate();
$this->EndResultCache();
}
Параметри StartResultCache($cacheTime, $cacheId, $cacheDir):
-
$cacheTime— TTL у секундах.falseабо0— кеш не використовується.-1— нескінченний кеш (до ручної інвалідації). -
$cacheId— унікальний ідентифікатор даного набору параметрів. При різних параметрах компонента має бути різним — інакше всі варіанти покажуть одні й ті самі дані. -
$cacheDir— папка в/bitrix/cache/. Потрібна для групового скидання кешу одного компонента.
Правильне формування cacheId
Помилка, яку допускають при першій реалізації: $cacheId не враховує всі параметри, що впливають на результат. У підсумку сторінка з розділом «Електроніка» показує кеш від сторінки «Одяг».
Що обов'язково має входити до cacheId:
$cacheId = serialize([
// Параметри компонента, що впливають на результат
$arParams['IBLOCK_ID'],
$arParams['SECTION_ID'],
$arParams['COUNT'],
$arParams['ELEMENT_SORT_FIELD'],
// Контекст
LANGUAGE_ID, // мультимовність
SITE_ID, // мультисайтовість
// Якщо контент залежить від групи користувача
// serialize(CSaleUser::GetUserGroups()), -- лише при потребі
]);
Не включати до cacheId те, що не впливає на дані — інакше кеш не буде використовуватись. Наприклад, CSS-клас блока ($arParams['CSS_CLASS']) — це параметр відображення, а не даних. Його застосовують у template.php напряму з $arParams, а не через $arResult.
Кеш з урахуванням груп користувачів
Якщо компонент показує різний контент авторизованим і гостям (наприклад, ціни для B2B-клієнтів відрізняються від роздрібних), кеш має бути роздільним:
// Варіант 1: кеш вимкнено для авторизованих користувачів
global $USER;
$cacheTime = $USER->IsAuthorized() ? false : $arParams['CACHE_TIME'];
// Варіант 2: увімкнути розподіл за групами (важче)
$arParams['CACHE_GROUPS'] = 'Y'; // параметр вмикає розподіл за групами у Бітрікс
Параметр CACHE_GROUPS => 'Y' у стандартних компонентах Бітрікс автоматично додає групи користувача до cacheId. У кастомному компоненті це потрібно зробити вручну:
if ($arParams['CACHE_GROUPS'] === 'Y') {
$userGroups = CSaleUser::GetUserGroups();
sort($userGroups);
$cacheId = serialize([$baseParams, $userGroups]);
}
Інвалідація кешу при оновленні даних
TTL-кеш (кеш за часом) — найпростіше рішення, але неточне: змінений о 10:00 елемент інфоблока стане видимим лише через 1 годину (якщо CACHE_TIME = 3600). Для контенту, де актуальність важлива, потрібна інвалідація за подією.
Обробник події інфоблока:
// У /local/php_interface/init.php
AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', 'clearMyComponentCache');
AddEventHandler('iblock', 'OnAfterIBlockElementAdd', 'clearMyComponentCache');
AddEventHandler('iblock', 'OnAfterIBlockElementDelete', 'clearMyComponentCache');
function clearMyComponentCache($arFields) {
// Скидаємо кеш лише для потрібного інфоблока
if (!in_array($arFields['IBLOCK_ID'], [IBLOCK_CATALOG_ID, IBLOCK_NEWS_ID])) {
return;
}
// Скидання всієї папки кешу компонента
BXClearCache(true, '/custom/my.component/' . $arFields['IBLOCK_ID'] . '/');
}
BXClearCache(true, $path) — видаляє всі файли у вказаній папці кешу. Швидко і без ORM.
Тегований кеш: точкова інвалідація
Якщо компонент показує дані з кількох інфоблоків, загальне скидання кешу при зміні будь-якого з них — марнотратство. Тегований кеш вирішує це точніше:
use Bitrix\Main\Data\TaggedCache;
$taggedCache = new TaggedCache();
$taggedCache->startTagCache('/custom/my.component/');
if ($this->StartResultCache($cacheTime, $cacheId, $cacheDir)) {
$taggedCache->registerTag('iblock_id_' . $arParams['IBLOCK_ID']);
$taggedCache->registerTag('iblock_element_' . $elementId); // при кешуванні конкретного елемента
$this->arResult = $this->getData();
$this->IncludeComponentTemplate();
$taggedCache->endTagCache();
$this->EndResultCache();
} else {
$taggedCache->abortTagCache();
}
Інвалідація за тегом при зміні конкретного елемента:
// В обробнику події
$taggedCache = new TaggedCache();
$taggedCache->clearByTag('iblock_element_' . $arFields['ID']);
$taggedCache->clearByTag('iblock_id_' . $arFields['IBLOCK_ID']);
Тегований кеш точніший, але вимагає більше коду. Виправданий для високонавантажених проєктів із частими оновленнями даних.
Налагодження кешу
Кеш можна вимкнути для конкретного компонента в режимі розробки:
// У component.php під час налагодження
$cacheTime = defined('DEVELOPER_MODE') && DEVELOPER_MODE ? false : $arParams['CACHE_TIME'];
DEVELOPER_MODE визначається у /bitrix/.settings.php або в константах проєкту. При false кеш пропускається, дані завжди запитуються з БД.
Перегляд кешу: файли у /bitrix/cache/ доступні напряму — це PHP-файли з даними serialize(). Час створення файлу — час останнього прогріву кешу.
Кеш та AJAX-запити
Для компонентів з AJAX-оновленням (підвантаження товарів при пагінації) кеш застосовується до кожного запиту окремо. cacheId для AJAX-запиту включає параметри запиту:
$page = max(1, (int)$_REQUEST['page']);
$cacheId = serialize([$baseParams, $page]);
Кожна сторінка пагінації кешується окремо — це правильно.
Терміни налаштування
| Завдання | Термін |
|---|---|
| Базове кешування для компонента | 2–4 години |
| + Інвалідація за подіями | 4–8 годин |
| + Тегований кеш | 1–2 дні |
| Аудит наявних компонентів + виправлення | 1–3 дні |
Кешування — одна з небагатьох оптимізацій, що дає миттєвий і вимірюваний результат. Правильно налаштований кеш знижує час генерації сторінки з 500 мс до 20–50 мс без зміни логіки застосунку.







