Skip to content

Instantly share code, notes, and snippets.

@if0rest
Last active December 11, 2021 19:34
Show Gist options
  • Save if0rest/574459c59491224833b4f2462369d64f to your computer and use it in GitHub Desktop.
Save if0rest/574459c59491224833b4f2462369d64f to your computer and use it in GitHub Desktop.

Кеширование выборки при ajax-запросе (старое ядро)

<?
define('TARGET_IBLOCK_ID', 1);

// Это то, что вернет скрипт
$arReturn = [
    'result' => 'error',
    'data'   => 'Неправильный запрос',
];

$sCode = $_POST["code"];

if ( !empty($sCode) )
{
    // Инициализируем php-кеширование (в хранилище кеша будет помещен json-объект)
    $cache = new CPHPCache();
    
    // Срок жизни кеша
    $cache_time = 86400*7;
    
    // Уникальный ID. Созданный кеш-файл будет именован его хеш-значением
    $cache_id = 'sectCache'.$sCode;
    
    // Папка для хранения кеша
    $cache_path = '/sectCache/'.$sCode;

    // Проверяем существование кеша
    if ( $cache->InitCache($cache_time, $cache_id, $cache_path) )
    {
        // Кеш есть, достаем данные
        $arCacheData = $cache->GetVars();
        
        // Достаем по ключу, с которым положили
        $arReturn['data'] = $arCacheData['sectCache'.$sCode];
    }
    else   // Кеша нет, нужно получить данные
    {
        if ( CModule::IncludeModule('iblock') )
        {
            $arSelect = [
                "ID",
                "NAME",
                "PROPERTY_YEAR",
            ];

            // Фильтр лучше использовать всегда, иначе при ошибке будет выбор всех элементов
            $arFilter = [
                'IBLOCK_ID' => TARGET_IBLOCK_ID,
                "ACTIVE"    => "Y",
            ];

            if ($sCode == "all-brands")
                $arFilter['INCLUDE_SUBSECTIONS'] = 'Y';
            else
                $arFilter['SECTION_CODE'] = $sCode;

            // Получаем данные
            $res = \CIBlockElement::GetList(["ID"=>"DESC"], $arFilter, false, false, $arSelect);

            // Массив элементов
            $arItems = [];

            while ($arElement = $res->Fetch())
            {
                $arElement["PREVIEW_PICTURE"] = CFile::GetPath($arElement["PREVIEW_PICTURE"]);
                $arItems[$arElement['ID']] = $arElement;
            }

            // Сохраняем данные в кеш
            // Чтобы кешировать HTML, заключите его между (start|end)DataCache()
            $cache->StartDataCache($cache_time, $cache_id, $cache_path);
            $cache->EndDataCache(['sectCache'.$sCode => $arItems]);

            $arReturn['data'] = $arItems;
        }
        else
        {
            $arReturn['data'] = "Модуль инфоблоков не подключен";
        }
    }
}

die(json_encode($arReturn));
?>

https://qna.habr.com/q/396075


Кеширование выборки при ajax-запросе (D7)

<?
define('TARGET_IBLOCK_ID', 1);

// Это то, что вернет скрипт
$arReturn = [
    'result' => 'error',
    'data'   => 'Неправильный запрос',
];

$sCode = \Bitrix\Main\Context::getCurrent()->getRequest()->getPost("code");

if (!empty($sCode))
{
    $cache = \Bitrix\Main\Data\Cache::createInstance();

    $cache_time = 86400*7;
    $cache_id   = 'sectCache'.$sCode;
    $cache_path = '/sectCache/'.$sCode;

    if ($cache->initCache($cache_time, $cache_id, $cache_path))
    {
        $arCachedVars = $cache->getVars();
        $arReturn['data'] = $arCachedVars['sectCache'.$sCode];
    }
    else
    {
        if (!\Bitrix\Main\Loader::includeModule('iblock'))
        {
            $arReturn['data'] = "Модуль инфоблоков не подключен";
        }
        else
        {
            $res = \CIBlockElement::GetList(
                array("ID" => "DESC"),
                array('IBLOCK_ID' => TARGET_IBLOCK_ID, "ACTIVE" => "Y"),
                false,
                false,
                array("ID", "NAME"),
            );

            $arItems = [];

            while ($arElement = $res->fetch()) {
                $arItems[ $arElement['ID'] ] = $arElement;
            }

            $cache->startDataCache();
            $cache->endDataCache(['sectCache'.$sCode => $arItems]);

            $arReturn['result'] = 'success';
            $arReturn['data']   = $arItems;
        }
    }
}

die(json_encode($arReturn));
?>

Реализация кеширования в компоненте средствами CPHPCache

<?
$obCache = new CPHPCache();

$cacheTTL  = $arParams["CACHE_TIME"];
$cacheID   = $arParams['IBLOCK_ID'] . $arParams['ELEMENT_ID'];
$cachePath = false;

// Проверяем существование актульного кеша
if ($obCache->InitCache($cacheTTL, $cacheID, $cachePath))
{
    // Получаем переменные
    $arVars   = $obCache->GetVars();
    $arResult = $arVars['arResult'];
    // Выводим HTML-кеш
    $obCache->Output();
}
// Иначе стартуем процесс кеширования
elseif ($obCache->StartDataCache())
{
    $itemItems = CIBlockElement::GetList([], $arFilter, false, false, $arSelect);

    while ($arItem = $itemItems->Fetch())
    {
        $arResult['ITEMS'][$arItem['ID']] = $arItem;
    }

    // Здесь же получаем итоговый HTML шаблона,
    // который также кешируем
    $this->IncludeComponentTemplate();

    // Список переменных для кеширования
    $obCache->EndDataCache([
        'arResult' => $arResult,
    ]);
}
?>

<?
// Кеш по определенному тегу можно очистить так:
$GLOBALS['CACHE_MANAGER']->ClearByTag("iblock_id_5");

// также можно очистить кеш по подразделу хранения:
$obCache = new CPHPCache();
$obCache->CleanDir('/myCache');     // Очищаем наш кеш
$obCache->CleanDir();               // а так можно очистить вообще весь кеш
?>

Кеширование выборок из БД

В версии 16.5.9 в ORM появилось кеширование выборок из базы данных. Чтобы закешировать результат getList, нужно задать ключ cache.Например, при получении элементов инфоблока:

$res = \Bitrix\Iblock\ElementTable::getList(array(
    'select' => array('ID', 'NAME', 'XML_ID'),
    'filter' => array('IBLOCK_ID' => 1),
    'cache'  => array(
        'ttl' => 60,
        'cache_joins' => true,
    )
));

$result = $res->fetch();

Параметров ttl задаётся время жизни кеша, а cache_joins задаёт необходимость кеширования при наличии джойнов. Внутри используется управляемое кеширование. Кеш пишется в папку /bitrix/managed_cache/MYSQL/orm_%имя_таблицы_сущности_orm%/ с ключом md5(%sql-запрос%).

В настройках CMS /bitrix/.settings.php можно задать глобальный диапазон ttl для отдельных таблиц с помощью настройки cache_flags:

'cache_flags' => array(
    'value'=> array(
        "b_iblock_element_min_ttl" => 60,
        "b_iblock_element_max_ttl" => 86400,
    )
),

Для того, чтобы очистить кеш выборок сущности, нужно вызвать метод cleanCache. Например, для элементов инфоблока:

\Bitrix\Iblock\ElementTable::getEntity()->cleanCache();

function getSliders()

<?
function getSliders($iblock_id)
{
    $cache      = new CPHPCache();
    $cache_time = 3600;
    $cache_id   = 'sliders' . $iblock_id;
    $cache_path = 'sliders';

    if ($cache->InitCache($cache_time, $cache_id, $cache_path))
    {
        $vars = $cache->GetVars();

        if (is_array($vars["sliders"]) && count($vars["sliders"]))
            $sliders = $vars["sliders"];
    }

    if (!is_array($sliders))
    {
        $query_rows = $GLOBALS['DB']->Query("
            SELECT b.ID as id, b.NAME as name, b.PREVIEW_PICTURE as picCode, b.PREVIEW_TEXT as url
            FROM b_iblock_element b
            WHERE b.IBLOCK_ID = 10 AND b.ACTIVE='Y'
            ORDER BY b.SORT ASC
        ");

        while ($slider = $query_rows->Fetch())
        {
            $sliders[$slider['id']] = $slider;
            $sliders[$slider['id']]['pic'] = CFile::GetPath($slider['picCode']);
        }

        $cache->StartDataCache($cache_time, $cache_id, $cache_path);
        $cache->EndDataCache(["sliders" => $sliders]);
    }

    return $sliders;
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment