Кеширование меню и лент новостей
Дата публикации: 31.07.2014
Версия системы: 2.9.5, TPL-шаблонизатор.
По мотивам рецепта //wiki.umisoft.ru/Кэширование_динамического_многоуровнего_меню.
Отличие: совместимость по параметрам со штатными макросами, использование штатного кеширующего механизма (я у себя тестировал на memcached)
Меню
Динамическое создание меню заметно нагружает систему, особенно, если оно содержит более одного уровня. И если новости и комментарии могут меняться часто, то меню у сайта, как правило, после этапа разработки остается в неизменном виде месяцами. Это можно использовать и снизить нагрузку на сервер (а, следовательно, уменьшить время генерации страницы), сохранив меню в кеш.
Что хочется от макроса: простота, легкость замены на него в уже имеющемся коде.
Ограничение: текущая страница в меню не выделяется. Можно учитывать в ключе и положение посетителя на сайте, чтобы подсвечивать текущий пункт меню, но это усложняет логику генерации ключа, увеличивает количество хранимых результатов и снижает эффективность кеширования. Считаю, что уж если так необходимо выделять текущий пункт, лучше переложить это дело на плечи яваскрипт.
Принцип работы: из переданных параметров, имени класса, имени метода формируем уникальный ключ, по которому результат работы макроса будет идентифицироваться в кеше. Я еще добавил имя хоста, чтобы избежать пересечения в случае, если на этом же сервере будет использоваться такой же макрос на другом сайте (memcached имеет общее хранилище)
Обращаю внимание на константы __CLASS__ и __METHOD__ , в которых содержатся имя текущего класса '__custom_content' и макроса 'menuCache' - два подчерка.
public function menuCache($menu_tpl = "default", $max_depth = 1, $pid = false){ $c = cmsController::getInstance(); $host = $c->getCurrentDomain(); //получаем имя хоста для использования в ключе $code = md5(__METHOD__.__CLASS__.$host.$menu_tpl.$max_depth.$pid); //формируем ключ $cacheFrontend = cacheFrontend::getInstance(); //вызываем кеш ЮМИ if($s = $cacheFrontend->loadData($code)) return $s; //если в нем есть запись с ключом $code, то возвращаем ее //генерируем меню $module = $c->getModule('content'); //получили объект класса модуля по имени $s = $module->menu($menu_tpl, $max_depth, $pid); //вызвали штатный макрос меню $cacheFrontend->saveData($code, $s, 3600); //сохранили в кеше на полчаса return $s; }
Называем макрос сходно со штатным, передаем ему те же параметры и в том же порядке, что и в штатный; это позволит в дальнейшем пройтись автозаменой по всем шаблонам.
Новости
Все то же применимо к макросу вывода лент новостей с тем дополнением, что нужно еще в ключ кеша включить номер страницы.
public function lastlistCache($path = "", $template = "default", $per_page = false, $ignore_paging = false, $sDaysInterval = '', $bSkipOrderByTime = false) { $module = cmsController::getInstance()->getModule('news'); if(!$per_page) $per_page = $module->per_page; $month = (int) getRequest('month'); $year = (int) getRequest('year'); $day = (int) getRequest('day'); $host = cmsController::getInstance()->getCurrentDomain(); $code = md5(__METHOD__.__CLASS__.$host.$path.$template.$per_page.$ignore_paging.$sDaysInterval.$bSkipOrderByTime.$month.$year.$day); $cacheFrontend = cacheFrontend::getInstance(); if($s = $cacheFrontend->loadData($code)) return $s; $s = $module->lastlist($path, $template, $per_page, $ignore_paging, $sDaysInterval, $bSkipOrderByTime); $cacheFrontend->saveData($code, $s, 1800); return $s; }
Добавлю еще, на этапе отладки бывает необходимо быстро очистить кеш. Это делается методом flush().
Казалось бы, методика найдена: делаешь кеширующую обертку и внутри нее вызываешь штатный макрос. Но тут на пути попался модуль "Баннеры"... Об этом следующая запись.