Битрикс. Классы CPHPCache и Cache

04.11.2018

Теги: CMSWeb-разработкаБитриксКешированиеКлассНовоеЯдроОтложенныеФункцииСтароеЯдро

Кеширование позволяет уменьшить нагрузку на аппаратные ресурсы, таким образом влияя на время отклика сайта. Используется как в стандартных компонентах, так и в компонентах, разработанных под свои нужды. Результаты ресурсоемких, а так же редко обновляемых кусков кода заносятся в кеш, при повторном запросе результат выдается из кеша.

Старое ядро

В старом ядре Битрикс для кеширования есть два класса — это CPageCache и CPHPCache. Первый служит для кеширования сформированного HTML-кода, второй — для кеширования HTML-кода и PHP-переменных. Файлы кеша записываются в каталог /bitrix/cache/.

Класс CPageCache

// подключаем модуль «Информационные блоки»
if (!CModule::IncludeModule('iblock')) {
    ShowError('Модуль «Информационные блоки» не установлен');
}

// тип инфоблока, откуда будем получать элемент инфоблока
$iblockType = 'content';
// идентификатор инфоблока, откуда будем получать элемент
$iblockId = 5;
// идентификатор элемента инфоблока, который надо показать
$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
        );
    }
}
Значение переменной $cacheDir начинается со слеша и им не заканчивается. При использовании в качестве кеша memcached это будет критичным при сбросе кеша.

Файл кеша /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-переменные:

// подключаем модуль «Информационные блоки»
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
        );
    }

}
Внутри HTML-кеша нельзя использовать отложенные функции. По той простой причине, что они просто не будут выполняться. Точнее говоря, функции будут выполнены один раз в момент создания файла кеша. А при всех последующих запросах будет выдано закешированное содержимое. Поэтому в коде выше функции SetTitle() и AddChainItem() вызываются за пределами HTML-кеша.

Файл кеша /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:"<h1>Ангорская кошка</h1>
<img src="/upload/iblock/57f/57f3872d827b2a94d61be9c999556d4b.jpg" border="0" alt="" width="500" height="500" />
<p>Ангорская кошка — порода домашних кошек, которая была создана европейскими и американскими селекционерами на
основе группы особей, вывезенных из Зоопарка Анкары в середине XX века. Турецкая ангора не только умна, но и
чрезвычайно адаптивна, ласкова и игрива.</p>";s:4:"VARS";a:2:{s:10:"iblockName";s:49:"Статьи о домашних
животных";s:11:"listPageURL";s:10:"/articles/";}}';
return true;
?>

Новое ядро

Аналогом CPHPCache в новом ядре является класс \Bitrix\Main\Data\Cache. Основные различия в методах в том, что названия методов нового класса пишутся с прописной буквы в соответствии с новыми требования оформления кода. В остальном внешне изменений практически нет:

use \Bitrix\Main\Data\Cache,
    \Bitrix\Main\Loader,
    \Bitrix\Iblock\Component\Tools;

// подключаем модуль «Информационные блоки»
if (!Loader::includeModule('iblock')) {
    ShowError('Модуль «Информационные блоки» не установлен');
}

// тип инфоблока, откуда будем получать элемент инфоблока
$iblockType = 'content';
// идентификатор инфоблока, откуда будем получать элемент
$iblockId = 5;
// идентификатор элемента инфоблока, который надо показать
$elementId = 354;
// если что-то пошло не так, эта переменная примет значение true
$notFound = false;

// получаем экземпляр класса
$cache = Cache::createInstance();

// время кеширования в секундах
$cacheTime = 3600; 
// формируем идентификатор кеша
$cacheId = $iblockType.$elementId;

if ($cache->initCache($cacheTime, $cacheId, '/another-cache-dir')) {
    /*
     * получаем закешированные переменные
     */
    $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]
        ..........

В конце названий всех директорий появится приписка из точки, тильды и длинного числа. После такой маркировки пути к файлам кеша изменятся, следовательно весь старый кеш сайта не будет восприниматься. Остаётся только все это удалить. И система сама это сделает: по агентам на хитах или кроне. Причём небольшими порциями, по несколько файлов за итерацию.

Поиск: CMS • Web-разработка • Битрикс • Класс • Кеширование • CPageCache • CPHPCache • Cache • StartDataCache • EndDataCache • AbortDataCache • InitCache • GetVars • createInstance • cleanDir • Старое ядро • Новое ядро • Отложенные функции

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.