Кеширование меню и лент новостей

Динамическое создание меню заметно нагружает систему, особенно, если оно содержит более одного уровня.  И если новости и комментарии могут меняться часто, то меню у сайта, как правило,  после этапа разработки остается в неизменном виде месяцами. Это можно использовать и снизить нагрузку на сервер (а, следовательно, уменьшить время генерации страницы), сохранив меню в кеш.

Дата публикации: 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().

 

Казалось бы, методика найдена: делаешь кеширующую обертку и внутри нее вызываешь штатный макрос. Но тут на пути попался модуль "Баннеры"...   Об этом следующая запись.