Кэширование в Modx Revo

май 3 , 2015
Метки:

Если Вы сделали несколько сайтов на Modx, то скорее всего уже сталкивались с проблемой кэширования и корректной очистки кэша. Ниже показывается, как работает кэш Modx и как создать плагин для очистки кэша одного ресурса.

Файловый кэш по умолчанию в Modx Revo работает не всегда так, как нам хочется. Что именно не так?

За кэширование документов в Modx отвечают 2 галочки на вкладке Настройки. Если отмечена галочка "Кэшируемый", а она отмечена по умолчанию, то при первом обращении к документу для него сохранится кэш в файле, из которого чтение будет происходить заметно быстрее. Если, конечно, у Вас не статичная страничка с чистым html. Отметив галочку "Очистить кэш", мы задаем принудительную очистку для того, чтобы при следующем обращении к ресурсу кэш пересоздался заново, и посетители сайта увидели сделанные нами изменения.

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

Все, что нам нужно, это создать плагин для очистки кэша конкретного ресурса при сохранении документа. При этом кэш других документов должен оставаться нетронутым. Решение подсмотрено у Василия Безумкина и немного расширено под наши нужды.

Итак, сам плагин. Нужно создать его под любым именем и назначить ему системные события OnDocFormRender и OnDocFormSave. На первом событии мы отключаем параметр "Очистить кэш". Можете убедиться в этом, включив плагин и открыв в админке любой документ - галочка будет снята. Второе событие вызывает код, очищающий кэш текущего документа.

    switch($modx->event->name) {
        case 'OnDocFormRender':
            $resource->set('syncsite', 0);
            break;
        
        case 'OnDocFormSave':
            if ($modx->event->params['mode'] != 'upd') {return;}
            $resource->_contextKey = $resource->context_key;
            $cache = $modx->cacheManager->getCacheProvider($modx->getOption('cache_resource_key', null, 'resource'));
            $key = $resource->getCacheKey();
            $cache->delete($key, array('deleteTop' => true));
            $cache->delete($key);
            break;
    }

Все работает отлично! Но теперь давайте посмотрим чуть дальше.

Допустим, у нас есть раздел "Все новости" на сайте, где транслируются заголовки и аннотации самих новостей. При сбросе кэша конкретной новости нужно еще "обнулить" и раздел "Все новости", ведь мы не обязательно будем править текст в поле content, а можем поменять pagetitle или introtext. Соответственно, кроме сброса кэша самого сохраняемого ресурса нужно еще сбросить другую страницу. К тому же, у нас могут быть и другие "сборные" страницы, которые работают по такому же принципу. Настроить очистку кэша для таких страниц несложно, нужно всего лишь дописать в наш плагин, в case OnDocFormSave несколько строк.

Давайте посмотрим на таком примере.
Предположим, у нас есть раздел "Все новости" с id=10, "Статьи" с id=15 и "Конкурсы" с id=50 . Сами новости имеют шаблон template=5. Плюс есть карта сайта (не путайте с sitemap.xml), где транслируются те же новости с id=100. Рассмотрим 2 варианта:

1. При редактировании отдельной новости, статьи или конкурса нужно очистить кэш соответствующих страниц-родителей

    // Ищем родителя сохраняемого ресурса
    $parent_id = $resource->get('parent');
    // Проверяем, наш ли это документ
    if(in_array($parent_id, array(10, 15, 50))) 
        $res=$modx->getObject('modResource', $parent_id);
        $cache = $modx->cacheManager->getCacheProvider($modx->getOption('cache_resource_key', null, 'resource'));
        $res->_contextKey = $res->context_key;
        $key = $res->getCacheKey();
        $cache->delete($key, array('deleteTop' => true));
        $cache->delete($key);
    }

2. Очищаем кэш карты сайта при редактировании новости - документа с шаблоном=5

    // Если редактируем страницу с указанным шаблоном
    if($resource->get('template') == 5) {
        // Получаем документ - карту сайта и очищаем его уже известным кодом
        $res = $modx->getObject('modResource', 100);
        $cache = $modx->cacheManager->getCacheProvider($modx->getOption('cache_resource_key', null, 'resource'));
        $res->_contextKey = $res->context_key;
        $key = $res->getCacheKey();
        $cache->delete($key, array('deleteTop' => true));
        $cache->delete($key);
    }

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

Метки:
Заходите в группу в контакте - https://vk.com/webdevkin
Анонсы статей, обсуждения интернет-магазинов, vue, фронтенда, php, гита.
Истории из жизни айти и обсуждение кода.
Как Вам статья? Оцените!