1С-Битрикс. Сбрасываем кеш инфоблоков, если наступило время активации или деактивации скидок каталога
Писал на одном проекте агент, который следит за скидками каталога и если подошло время акции или деактивации скидки, то сбрасывает кеш нужных инфоблоков или же всего сайта.
Поясню: менеджер заводит скидку на товары, которая должна активироваться в 20:00 вечера, а деактивироваться в 3 часа ночи следующего дня. Если у компонента, который выводит товары каталога, в параметрах время жизни кеша большое, то цены со скидками в каталоге не появятся пока вы не сбросите кеш. Мой агент эту проблему решает. Можно заводить отложенные скидки и идти спокойно спать :)
Решил поделиться, так как этот кейс нередко просят добавить.
Так как алгоритм агента довольно прост, есть некоторые особенности для корректной работы агента (с настройками по умолчанию):
- Агенты сайта должны работать по крону, с периодичностью в 1 минуту
- Возможен оверхед на одно лишнее сбрасывание кеша, при активации/деактивации скидки
Если агенты сайта не на кроне, то агент сброса кеша будет срабатывать только в момент посещения пользователями сайта, что теряет смысл в его целесообразности.
Код агента
/** * Created by olegpro.ru. * User: Oleg Maksimenko <oleg.39style@gmail.com> * Date: 24.01.2016 */ namespace Olegpro\Agents; use Bitrix\Main\Config\Option; use Bitrix\Main\Type; use Bitrix\Main\Diag\Debug; class CatalogDiscountAgent { /** * @param int $minutes * @return string * @throws \Bitrix\Main\LoaderException */ public static function clearExpiredCache($minutes = 1) { $minutes = abs($minutes > 0 ? $minutes : 1); $useLog = (Option::get('main', '~use_log_agent_catalog_discount_clear_cache', 'N') === 'Y'); // Ids iblocks at which you need to clear the cache $iblockIds = array( 1, ); $needClear = false; if (\Bitrix\Main\Loader::includeModule('catalog')) { $fromDate = new Type\DateTime(); $fromDate ->add(sprintf('-%s minutes', $minutes)) ->add(sprintf('-%d seconds', $fromDate->format('s'))) ; $toDate = new Type\DateTime(); $toDate ->add(sprintf('+%s minutes', $minutes)) ->add(sprintf('-%d seconds', $toDate->format('s'))) ; // started /** @noinspection PhpDynamicAsStaticMethodCallInspection */ $catalogDiscountIterator = \CCatalogDiscount::GetList( array('ID' => 'DESC',), array( '>=ACTIVE_TO' => $fromDate, '<=ACTIVE_TO' => $toDate, ), false, false, array('ID', 'NAME', 'ACTIVE_FROM', 'ACTIVE_TO') ); if ($catalogDiscount = $catalogDiscountIterator->Fetch()) { $needClear = true; if ($useLog) { Debug::writeToFile( sprintf( '%s', print_r($catalogDiscount, 1) . PHP_EOL . print_r( array( '>=ACTIVE_TO' => $fromDate, '<=ACTIVE_TO' => $toDate, ), 1 ) ), sprintf('%s, %s - started "to"', __METHOD__, date('d-m-Y H:i:s')), 'agent_catalog_discount_clear_cache.log' ); Debug::writeToFile( sprintf( '$needClear=%s, $catalogDiscount=%s', var_export($needClear, true), var_export($catalogDiscount, true) ), sprintf('%s, %s - started "to"', __METHOD__, date('d-m-Y H:i:s')), 'agent_catalog_discount_clear_cache.log' ); } } // finished /** @noinspection PhpDynamicAsStaticMethodCallInspection */ $catalogDiscountIterator = \CCatalogDiscount::GetList( array('ID' => 'DESC',), array( '>=ACTIVE_FROM' => $fromDate, '<=ACTIVE_FROM' => $toDate, ), false, false, array('ID', 'NAME', 'ACTIVE_FROM', 'ACTIVE_TO') ); if ($catalogDiscount = $catalogDiscountIterator->Fetch()) { $needClear = true; if ($useLog) { Debug::writeToFile( sprintf( '%s', print_r($catalogDiscount, 1) . PHP_EOL . print_r( array( '>=ACTIVE_FROM' => $fromDate, '<=ACTIVE_FROM' => $toDate, ), 1 ) ), sprintf('%s, %s - finished "from"', __METHOD__, date('d-m-Y H:i:s')), 'agent_catalog_discount_clear_cache.log' ); Debug::writeToFile( sprintf( '$needClear=%s, $catalogDiscount=%s', var_export($needClear, true), var_export($catalogDiscount, true) ), sprintf('%s, %s - finished "from"', __METHOD__, date('d-m-Y H:i:s')), 'agent_catalog_discount_clear_cache.log' ); } } } if ($needClear) { // >= iblock 15.0.7 if (method_exists('\CIBlock', 'clearIblockTagCache')) { \CIBlock::enableClearTagCache(); foreach ($iblockIds as $iblockId) { \CIBlock::clearIblockTagCache($iblockId); } \CIBlock::DisableClearTagCache(); } else { BXClearCache(true); (new \Bitrix\Main\Data\ManagedCache())->cleanAll(); (new \CStackCacheManager())->CleanAll(); } if ( method_exists('\CHTMLPagesCache', 'IsCompositeEnabled') && \CHTMLPagesCache::IsCompositeEnabled() ) { \CHTMLPagesCache::CleanAll(); } } return '\\' . __METHOD__ . '();'; } }
Как обычно, копируем код класса, размещаем в удобном месте и добавляем в автозагрузку.
Если ваша версия модуля инфоблоков >= 15.0.7, то нужно в массив $iblockIds добавить ID инфоблоков, для которых вы хотите сбрасывать кеш. Иначе будет сброшен кеш всего сайта.
В коде класса агента оставлена возможность отладки. Активируется опцией (можно через коммандную php-строку битрикса):
\Bitrix\Main\Config\Option::set('main', '~use_log_agent_catalog_discount_clear_cache', 'Y');
После этого добавляем агент в систему (можно через коммандную php-строку битрикса):
\CAgent::AddAgent('\Olegpro\Agents\CatalogDiscountAgent::clearExpiredCache();', '', 'Y', 60, '', 'N', '');