Классы CPHPCache и Cache
Кеширование позволяет уменьшить нагрузку на аппаратные ресурсы, таким образом влияя на время отклика сайта. Используется как в стандартных компонентах, так и в компонентах, разработанных под свои нужды. Результаты ресурсоемких, а так же редко обновляемых кусков кода заносятся в кеш, при повторном запросе результат выдается из кеша.
Старое ядро
В старом ядре Битрикс для кеширования есть два класса — это CPageCache
и CPHPCache
. Первый
служит для кеширования сформированного HTML-кода, второй — для кеширования HTML-кода и PHP-переменных. Файлы кеша
записываются в каталог /bitrix/cache/
.
CPageCache
Кеширование HTML кода:
Значение переменной $cacheDir начинается со слеша и им не заканчивается. При использовании в качестве кеша memcached это будет критичным при сбросе кеша
// подключаем модуль «Информационные блоки»
if (!CModule::IncludeModule('iblock')) {
ShowError('Модуль «Информационные блоки» не установлен');
}
// тип инфоблока, откуда будем получать элемент инфоблока
$iblockType = 'content';
// идентификатор элемента инфоблока, который надо показать
$elementId = 354;
// создаем объект кеша
$pageCache = new CPageCache();
// время кеширования в секундах
$cacheTime = 3600;
// формируем идентификатор кеша в зависимости от всех параметров, которые могут повлиять на результирующий HTML-код
$cacheId = $iblockType.$elementId;
// директороия для хранения файлов кеша
$cacheDir = '/some-cache-dir';
// начинаем буферизацию вывода
if ($pageCache->StartDataCache($cacheTime, $cacheId, $cacheDir)) {
// выбираем из базы данных элемент инфоблока
if ($arElement = GetIBlockElement($elementId, $iblockType)) {
// выводим заголовок страницы
echo '<h1>'.$arElement['NAME'].'</h1>', PHP_EOL;
// выводим картинку
echo CFile::ShowImage($arElement['DETAIL_PICTURE'], 500, 500), PHP_EOL;
// выводим краткое описание
echo '<p>'.$arElement['PREVIEW_TEXT'].'</p>';
// записываем буферизированный вывод в файл кеша
$pageCache->EndDataCache();
} else {
$pageCache->AbortDataCache();
\Bitrix\Iblock\Component\Tools::process404(
'Страница не найдена',
true,
true
);
}
}
Файл кеша /bitrix/cache/some-cache-dir/47/476bb6ea1797242d5401ed9ec02c831e.html
содержит в себе отметку
времени (функция time()
) — когда она станет меньше текущей, кеш уже не актуален:
BX001541320265001541320265<h1>Ангорская кошка</h1>
<img src="/upload/iblock/57f/57f3872d827b2a94d61be9c999556d4b.jpg" border="0" alt="" width="500" height="500" />
<p>Ангорская кошка — порода домашних кошек, которая была создана европейскими и американскими селекционерами на
основе группы особей, вывезенных из Зоопарка Анкары в середине XX века. Турецкая ангора не только умна, но и
чрезвычайно адаптивна, ласкова и игрива.</p>
CPHPCache
Кеширование PHP кода:
// подключаем модуль «Информационные блоки»
if (!CModule::IncludeModule('iblock')) {
ShowError('Модуль «Информационные блоки» не установлен');
}
// тип инфоблока, откуда будем получать элемент инфоблока
$iblockType = 'content';
// идентификатор инфоблока, откуда будем получать элемент
$iblockId = 5;
// идентификатор элемента инфоблока, который надо показать
$elementId = 354;
// если что-то пошло не так, эта переменная примет значение true
$notFound = false;
// создаем объект кеша
$phpCache = new CPHPCache();
// время кеширования в секундах
$cacheTime = 3600;
// формируем идентификатор кеша в зависимости от всех параметров, которые могут повлиять на PHP-переменные
$cacheId = $iblockType.$elementId;
if ($phpCache->InitCache($cacheTime, $cacheId, '/other-cache-dir')) { // если кеш есть и он еще актуален
// получаем закешированные переменные
$data = $phpCache->GetVars();
// данные об инфоблоке
$iblockName = $data['iblockName'];
$listPageURL = $data['listPageURL'];
// данные об элементе инфоблока
$elementName = $data['elementName'];
$elementPicture = $data['elementPicture'];
$elementPreview = $data['elementPreview'];
} else { // иначе обращаемся к базе
// данные об инфоблоке
$arIblock = GetIBlock($iblockId, $iblockType);
// данные об элементе инфоблока
$arElement = GetIBlockElement($elementId, $iblockType);
// если данные успешно получены
if ($arIblock && $arElement) {
$iblockName = $arIblock['NAME'];
$listPageURL = $arIblock['LIST_PAGE_URL'];
$elementName = $arElement['NAME'];
$elementPicture = $arElement['DETAIL_PICTURE'];
$elementPreview = $arElement['PREVIEW_TEXT'];
// записываем полученные данные в кеш
$phpCache->StartDataCache();
$phpCache->EndDataCache(
array(
'iblockName' => $iblockName,
'listPageURL' => $listPageURL,
'elementName' => $elementName,
'elementPicture' => $elementPicture,
'elementPreview' => $elementPreview
)
);
} else { // что-то пошло не так
$notFound = true;
}
}
if (!$notFound) { // все хорошо, все данные получены
// в заголовок страницы вставим название элемента
$APPLICATION->SetTitle($elementName);
// добавим пункт меню в навигационную цепочку
$APPLICATION->AddChainItem($iblockName, $listPageURL);
// выводим заголовок страницы
echo '<h1>'.$elementName.'</h1>', PHP_EOL;
// выводим картинку
echo CFile::ShowImage($elementPicture, 500, 500), PHP_EOL;
// выводим краткое описание
echo '<p>'.$elementPreview.'</p>';
} else { // что-то пошло не так
\Bitrix\Iblock\Component\Tools::process404(
'Страница не найдена',
true,
true
);
}
Файл кеша /bitrix/cache/other-cache-dir/47/476bb6ea1797242d5401ed9ec02c831e.php
:
<?
if ($INCLUDE_FROM_CACHE!='Y') return false;
$datecreate = '001541323175';
$dateexpire = '001541326775';
$ser_content = 'a:2:{s:7:"CONTENT";s:0:"";s:4:"VARS";a:5:{s:10:"iblockName";s:49:"Статьи о домашних
животных";s:11:"listPageURL";s:10:"/articles/";s:11:"elementName";s:29:"Ангорская
кошка";s:14:"elementPicture";s:4:"1025";s:14:"elementPreview";s:473:"Ангорская кошка — порода домашних
кошек, которая была создана европейскими и американскими селекционерами на основе группы особей,
вывезенных из Зоопарка Анкары в середине XX века. Турецкая ангора не только умна, но и чрезвычайно
адаптивна, ласкова и игрива.";}}';
return true;
?>
В кеш сохраняем HTML и PHP
Внутри HTML-кеша нельзя использовать отложенные функции. По той простой причине, что они просто не будут
выполняться. Точнее говоря, функции будут выполнены один раз в момент создания файла кеша. А при всех последующих
запросах будет выдано закешированное содержимое. Поэтому в коде выше функции SetTitle()
и
AddChainItem()
вызываются за пределами HTML-кеша.
// подключаем модуль «Информационные блоки»
if (!CModule::IncludeModule('iblock')) {
ShowError('Модуль «Информационные блоки» не установлен');
}
// тип инфоблока, откуда будем получать элемент инфоблока
$iblockType = 'content';
// идентификатор инфоблока, откуда будем получать элемент
$iblockId = 5;
// идентификатор элемента инфоблока, который надо показать
$elementId = 354;
// создаем объект кеша
$phpCache = new CPHPCache();
// время кеширования в секундах
$cacheTime = 3600;
// формируем идентификатор кеша в зависимости от всех параметров, которые могут повлиять на HTML-код и PHP-переменные
$cacheId = $iblockType.$elementId;
// если кеш есть и он еще актуален
if ($phpCache->InitCache($cacheTime, $cacheId, '/other-cache-dir')) {
// получаем закешированные переменные
$data = $phpCache->GetVars();
$iblockName = $data['iblockName'];
$listPageURL = $data['listPageURL'];
} else {
// иначе обращаемся к базе
$data = GetIBlock($iblockId, $iblockType);
$iblockName = $data['NAME'];
$listPageURL = $data['LIST_PAGE_URL'];
}
// в заголовок страницы вставим название инфоблока
$APPLICATION->SetTitle($iblockName);
// добавим пункт меню в навигационную цепочку
$APPLICATION->AddChainItem($iblockName, $listPageURL);
// начинаем буферизацию вывода
if ($phpCache->StartDataCache()) {
// выбираем из базы данных элемент инфоблока
if ($arElement = GetIBlockElement($elementId, $iblockType)) {
// выводим заголовок страницы
echo '<h1>'.$arElement['NAME'].'</h1>', PHP_EOL;
// выводим картинку
echo CFile::ShowImage($arElement['DETAIL_PICTURE'], 500, 500), PHP_EOL;
// выводим краткое описание
echo '<p>'.$arElement['PREVIEW_TEXT'].'</p>';
// записываем предварительно буферизированный вывод в файл кеша вместе с дополнительными переменными
$phpCache->EndDataCache(
array(
'iblockName' => $iblockName,
'listPageURL' => $listPageURL
)
);
} else {
$phpCache->AbortDataCache();
\Bitrix\Iblock\Component\Tools::process404(
'Страница не найдена',
true,
true
);
}
}
Файл кеша /bitrix/cache/other-cache-dir/47/476bb6ea1797242d5401ed9ec02c831e.php
:
<?
if ($INCLUDE_FROM_CACHE!='Y') return false;
$datecreate = '001541406065';
$dateexpire = '001541409665';
$ser_content = 'a:2:{s:7:"CONTENT";s:671:"Ангорская кошка
Ангорская кошка — порода домашних кошек, которая была создана европейскими и американскими селекционерами на
основе группы особей, вывезенных из Зоопарка Анкары в середине XX века. Турецкая ангора не только умна, но и
чрезвычайно адаптивна, ласкова и игрива.
";s:4:"VARS";a:2:{s:10:"iblockName";s:49:"Статьи о домашних
животных";s:11:"listPageURL";s:10:"/articles/";}}';
return true;
?>
Новое ядро
Аналогом CPHPCache
в новом ядре является класс \Bitrix\Main\Data\Cache
. Основные различия
в методах в том, что названия методов нового класса пишутся с прописной буквы в соответствии с новыми требования
оформления кода. В остальном внешне изменений практически нет:
// класс для кеширования PHP переменных и HTML
use \Bitrix\Main\Data\Cache;
// класс для загрузки необходимых файлов, классов и модулей
use \Bitrix\Main\Loader;
// класс для работы с 404 ошибкой
use \Bitrix\Iblock\Component\Tools;
// подключаем модуль «Информационные блоки»
if (!Loader::includeModule('iblock')) {
ShowError('Модуль «Информационные блоки» не установлен');
}
// тип инфоблока, откуда будем получать элемент инфоблока
$iblockType = 'bannery';
// идентификатор инфоблока, откуда будем получать элемент
$iblockId = 1;
// идентификатор элемента инфоблока, который надо показать
$elementId = 186;
// если что-то пошло не так, эта переменная примет значение true
$notFound = false;
// получаем экземпляр класса
$cache = Cache::createInstance();
// время кеширования в секундах
$cacheTime = 3600;
// формируем идентификатор кеша
$cacheId = $iblockType.$elementId;
if ($cache->initCache($cacheTime, $cacheId, '/another-cache-dir')) { // получаем закешированные переменные
// получаем PHP переменные сохраненные в кеше
$data = $cache->getVars();
// данные об инфоблоке
$iblockName = $data['iblockName'];
$listPageURL = $data['listPageURL'];
// данные об элементе инфоблока
$elementName = $data['elementName'];
$elementPicture = $data['elementPicture'];
$elementPreview = $data['elementPreview'];
} elseif ($cache->startDataCache()) { // иначе обращаемся к базе
// данные об инфоблоке
$arIblock = GetIBlock($iblockId, $iblockType);
// данные об элементе инфоблока
$arElement = GetIBlockElement($elementId, $iblockType);
if ($arIblock && $arElement) { // если данные успешно получены
$iblockName = $arIblock['NAME'];
$listPageURL = $arIblock['LIST_PAGE_URL'];
$elementName = $arElement['NAME'];
$elementPicture = $arElement['DETAIL_PICTURE'];
$elementPreview = $arElement['PREVIEW_TEXT'];
// записываем полученные данные в кеш
$cache->endDataCache(
array(
'iblockName' => $iblockName,
'listPageURL' => $listPageURL,
'elementName' => $elementName,
'elementPicture' => $elementPicture,
'elementPreview' => $elementPreview
)
);
} else { // что-то пошло не так
$cache->abortDataCache();
$notFound = true;
}
}
if (!$notFound) { // все хорошо, все данные получены
// в заголовок страницы вставим название элемента
$APPLICATION->SetTitle($elementName);
// добавим пункт меню в навигационную цепочку
$APPLICATION->AddChainItem($iblockName, $listPageURL);
// выводим заголовок страницы
echo '<h1>'.$elementName.'</h1>', PHP_EOL;
// выводим картинку
echo CFile::ShowImage($elementPicture, 500, 500), PHP_EOL;
// выводим краткое описание
echo '<p>'.$elementPreview.'</p>';
} else { // что-то пошло не так
Tools::process404(
'Страница не найдена',
true,
true
);
}
Файл кеша /bitrix/cache/another-cache-dir/47/476bb6ea1797242d5401ed9ec02c831e.php
:
<?
if ($INCLUDE_FROM_CACHE!='Y') return false;
$datecreate = '001541325078';
$dateexpire = '001541328678';
$ser_content = 'a:2:{s:7:"CONTENT";s:0:"";s:4:"VARS";a:5:{s:10:"iblockName";s:49:"Статьи о домашних
животных";s:11:"listPageURL";s:10:"/articles/";s:11:"elementName";s:29:"Ангорская
кошка";s:14:"elementPicture";s:4:"1025";s:14:"elementPreview";s:473:"Ангорская кошка — порода домашних
кошек, которая была создана европейскими и американскими селекционерами на основе группы особей,
вывезенных из Зоопарка Анкары в середине XX века. Турецкая ангора не только умна, но и чрезвычайно
адаптивна, ласкова и игрива.";}}';
return true;
?>
Очистка кеша
Очистить кеш, сохраненный в директории /bitrix/cache/another-cache-dir/
можно следующим образом:
$cache = \Bitrix\Main\Data\Cache::createInstance();
$cache->cleanDir('/another-cache-dir');
Очистить весь кеш (т.е. все содержимое директории /bitrix/cache/
):
$cache = \Bitrix\Main\Data\Cache::createInstance();
$cache->cleanDir();
Этот код промаркирует директрии кеша на удаление. В конце названий всех директорий появится приписка из точки, тильды и длинного числа. После такой маркировки пути к файлам кеша изменятся, следовательно весь старый кеш сайта не будет восприниматься. Остаётся только все это удалить. И система сама это сделает: по агентам на хитах или кроне. Причём небольшими порциями, по несколько файлов за итерацию.
[bitrix]
[cache]
[another-cache-dir.~917285]
[other-cache-dir.~578322]
[some-cache-dir.~881386]
..........