вторник, 12 ноября 2013 г.

Битрикс. Зависимые по содержанию блоки.

Допустим, нам надо сделать блок в шаблоне сайта с содержанием, зависимым от того, где мы сейчас находимся и что показываем. Сформулируем более чёткие требования:
  1. На детальной странице новости мы показываем в требуемом блоке пару новостей из этого же раздела и с хотя бы с одним совпадением тегов из показываемой новости.
  2. Если совпадений нет, то просто показываем новости из того же раздела. Показываем новости из этого же раздела на странице списка новостей раздела.
  3. Если и сейчас не хватает - показываем любые из ИБ Новости.
  4. Не забыть про кеширование.
Кстати, сортировка рандомная.

Разговор сегодня будет долгий. Обсуждаем новые отложенные функции, которые почему-то в документации не рекомендуют использовать, а на курсах учили использовать. Также используем для своих вполне понятных целей встроенный класс кеширования, чтобы управлять кешированием нашего блока с помощью стандартных инструментов администрирования.


Мы в курсе того, что у Битрикса есть механизм отложенных функций; лезем в документацию по новым отложенным функциям: Новые методы буферизации

Продумываем логику реализации. Нам будут нужны:
  1. вспомогательная функция-отдавалка, которая будет отдавать список новостей для блока. 
  2. основная функция-кешировалка, которая будет управлять кешированием и отдавать конечный код для блока. она будет спрашивать функцию-отдавалку.

Так как содержимое блока зависит от того, какая сейчас новость показывается, то мы будем спрашивать кешировалку в темплейте компонента. Файл result_modifier темплейта кешируется средствами компонента, то нам этот файл для формирования содержимого не подходит. Естественно, мы будем спрашивать кешировалку в файле component_epilog.

Вроде всё продумали, приступаем к реализации.

1. Размещение отложенных методов.

У меня в шаблоне сайта описываемый блок находится в футере в html для колонки справа. На место вёрстки вставляю функцию-приёмник "отложенных данных".
$APPLICATION->ShowViewContent("right_adnews");
Здесь right_adnews - это имя метки, в которую мы будет передавать данные.

Для формирования отложенных данных будем использовать
$APPLICATION->AddViewContent('right_adnews', $str, 500);
Здесь right_adnews - это имя метки, куда уйдут данные, str - переменная, содержащая html-код для показа, 500 - сортировка. 
С размещением тут всё интереснее. Во-первых, мы вспоминаем, что в component_epilog приходят далеко не весь arResult, который доступен в result_modifier =) Для доступности нужных нам данных надо дополнительно указать ключи из arResult, которые должны быть доступны в component_epilog. То есть в конце файла result_modifier надо написать
$this->__component->arResultCacheKeys = array_merge($this->__component->arResultCacheKeys, array('ID', 'IBLOCK_SECTION_ID', 'TAGS'));

И весь код component_epilog сводится к двум строчкам:
$str = ProjectCommonLib::cacheAdProblems($arResult);
$APPLICATION->AddViewContent('right_adblock', $str, 500);
ProjectCommonLib - это класс с общими для всего текущего проекта функциями; нам нравится когда такие функции оформлены в класс, не буду отходить от организационного стандарта (сами понимаете, что класс должен быть включён в init.php); cacheAdProblems - это функция-кешировалка.

2. Отдавалка.

Это вспомогательная функция, которая будет отдавать массив новостей для кешировалки. Сначала, естественно, возникает желание передавать туда айди новости и на основе этого формировать список соответствующих новостей для блока. Но мы не зря засунули вызов кешировалки в компонент - в компоненты уже есть все нужные нам данные и не  надо лишний раз их получать.
Итак, в отдавалку мы будем передавать айди новости, айди раздела текущей новости или текущего списка новостей, список тегов. Не забываем, что каждого из этих аргументов может не быть: в крайнем случае, выдаётся просто рандомная пара элементов.
Позвольте не захламлять статью кодом получения списка новостей по заданным фильтрам, если уже вы добрались до механизма отложенных функций, то и список из ИБ можете сами получить =)

3.Кешировалка.

Кешировалка получает на вход массив arResult с нужными данными. При их отсутствии плавно расширяется круг новостей, которые можно включить в поиск - это делает функция-отдавалка, кешировалке это всё равно.
Давайте сразу смотреть в код и в комментарии.
//создаёт объект
$obCache = new CPHPCache; 
// время кеширования указывается в секундах
$life_time = 2*60; // две минуты
// имя кеша формируем зависимым от айди проблемы и айди секции
$cache_id = "s1_adproblem".(int)$arResult['ID']."_".(int)$arResult['IBLOCK_SECTION_ID'];

//если кеш создан и не протух
if($obCache->InitCache($life_time, $cache_id, "/"))
{
 // получаем закешированные данные
 $arCache = $obCache->GetVars();
 $arAdItems = $arCache["RESULT"];
}
elseif ($obCache->StartDataCache())
{
 //делаем тяжёлые вычисления
 $arAdItems = ProjectCommonLib::_getAdNews($arResult['ID'], $arResult['IBLOCK_SECTION_ID'], $arResult['TAGS']);
 //сохраняем в кеш
 $obCache->EndDataCache(array("RESULT"=>$arAdItems));
}

//здесь формируем строку для показа
foreach ($arAdItems as $arAd)
{
 //создаём здесь дизайн по вёрстке
 //запихиваем его в строковую переменную
}

Кешировалка возвращает строковую переменную с html-кодом, соответствующим вёрстке.Эту переменную мы отдаём в качестве второго аргумента функции AddViewContent (см. пункт 1. Размещение отложенных методов).

Вот, собственно, и всё. Проверить работу кеша можно например в режиме Суммарной статистики, обновляя страницу просто так и обновляя эрмитажной кнопкой Сбросить кеш.







Комментариев нет:

Отправить комментарий