До появления удобной обёртки Bitrix\Main\Data\Cache
в D7, ручное кеширование в Битриксе строилось на классе
CPHPCache. Он до сих пор встречается в старом коде
и в некоторых сценариях остаётся рабочим вариантом. Разберём его
устройство и чем он отличается от современной обёртки.
Базовое использование
<?php
$cache = new CPHPCache;
$cacheTime = 3600;
$cacheId = 'my_data_' . $categoryId;
$cacheDir = '/my_module/category/';
if ($cache->InitCache($cacheTime, $cacheId, $cacheDir)) {
$data = $cache->GetVars();
} elseif ($cache->StartDataCache()) {
$data = getHeavyData($categoryId); // тяжёлая операция
$cache->EndDataCache($data);
}
// использовать $data дальше
Логика та же, что и в D7-обёртке: проверка наличия валидного
кеша, при отсутствии — вычисление данных и сохранение результата.
Разница в основном в стиле API — CPHPCache использует
методы в стиле CamelCase старого ядра, а не пространства имён
и статические фабричные методы D7.
Отмена сохранения при некорректных данных
<?php
if ($cache->StartDataCache()) {
$data = getHeavyData($categoryId);
if (empty($data)) {
$cache->AbortDataCache(); // не сохранять пустой результат
} else {
$cache->EndDataCache($data);
}
}
AbortDataCache — важный метод, о котором часто
забывают: без явной отмены при неудачном вычислении данных
(например, временный сбой внешнего API, откуда берутся данные)
в кеш может записаться пустой или частичный результат, который
затем будет отдаваться из кеша как валидный на протяжении всего
срока жизни кеша, маскируя реальную временную проблему длительным
показом пустых данных.
Нужна помощь с Битрикс?
Принудительная очистка конкретного кеша
<?php
$cache = new CPHPCache;
$cache->CleanDir('/my_module/category/');
Очистка по каталогу кеша полезна, когда данные изменились программно и нужно немедленно инвалидировать связанный кеш, не дожидаясь истечения срока его жизни, — типичный сценарий: вызов очистки в обработчике события изменения данных, от которых зависит закешированный результат.
Почему D7-обёртка предпочтительнее для нового кода
Bitrix\Main\Data\Cache добавляет поддержку тегированного
кеша — возможность связать закешированные данные с определённым
тегом и инвалидировать сразу все связанные записи по этому тегу,
без необходимости помнить точный путь каждого отдельного кеша.
CPHPCache такой возможности не имеет — управление
инвалидацией лежит полностью на разработчике, вручную вызывающем
CleanDir в нужных местах.
Совместимость: можно ли смешивать оба подхода
Оба механизма физически используют одну и ту же файловую систему кеша под капотом, но обращаться к одному и тому же кешу через разные API в разных частях проекта не стоит — это усложняет понимание того, где и как конкретный кеш инвалидируется, без реальной технической необходимости смешивать подходы в рамках одного модуля.
Когда CPHPCache всё ещё оправдан
Для проектов, где большая часть кода уже написана на старом API
без D7, использование CPHPCache в новом коде того же
модуля может быть оправдано ради единообразия стиля — переписывать
весь модуль на D7 ради одного нового куска кеширования не всегда
оправданная трата времени, если модуль в целом не планируется
переводить на D7 в обозримой перспективе.
Частые ошибки
- Не вызван AbortDataCache при неудачном вычислении данных. Пустой или ошибочный результат сохраняется в кеш как валидный на весь срок жизни.
- Использованы оба API (CPHPCache и D7-Cache) для одного и того же кеша в разных местах. Затрудняет понимание логики инвалидации.
- Новый модуль пишется на CPHPCache без веской причины. Теряется доступ к тегированной инвалидации D7-обёртки без реальной необходимости.
Итог
CPHPCache остаётся рабочим инструментом кеширования,
особенно в старом коде, но не даёт тегированной инвалидации,
доступной в D7-обёртке Bitrix\Main\Data\Cache. Для
нового кода D7-вариант предпочтителен, а при использовании старого
API критично не забывать AbortDataCache при неудачном
вычислении данных — иначе временный сбой превращается в длительный
показ некорректного закешированного результата.
