Как не чистить кэш всего сайта?

Постоянно задают вопросы «а как при сохранении чистить кэш не всего сайта, а только обновляемого ресурса?».
А вот так:

<?php
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;
}
Создать плагин с любым именем, назначить ему события OnDocFormRender и OnDocFormSave, скопипастить.

Первое событие плагина убирает галочку «Очистить кэш» у формы редактирования ресурса. Если включить ее вручную — кэш будет очищен, как обычно.
Второе — получает обработчика кэша ресурсов и говорит ему удалить запись нужного документа. Все остальные не трогаются.

У простых ресурсов кэш хранится в одном файле, у сложных (где вызываются кэшируемые сниппеты) — в директории. Поэтому, мы чистим сначала директорию, а потом и файл, чтобы наверняка.

С компонентом Articles этот фокус не работает — там нет syncsite в админке.

Следующая заметка
Тег spoiler для Jevix
Предыдущая заметка
Wayfinder и количество документов в контейнере


Комментарии ()

  1. Денис 09 ноября 2012, 16:22 # 0
    Спасибо большое!
    1. Антон Слободчук 09 ноября 2012, 16:40 # 0
      Странно, что разработчики MODX не добавили эту функциональность по умолчанию. Я думал, что это связано с тем, что «куски» кэша ресурса могут хранится не только в /resources/id-ресурса.
      1. Иван Брежнев 09 ноября 2012, 17:04 # 0
        Нет, они не добавили потому что ресурс может быть использован в списках, и при обновлении одного ресурса список останется со старыми данными
        1. Иван Брежнев 09 ноября 2012, 17:05 # 0
          Просто нужно заранее предусмотреть где и что вам нужно чистить
          1. Andrei Kilin 09 ноября 2012, 17:05 # 0
            Василий уже писал об этом. Да, из-за возможных хитрых взаимодействий ресурсов приходится чистить весь кэш. http://modx.com/blog/2012/10/29/optimization-with-getcache-and-custom-cache-partitions/
          2. Alexander Orel 11 ноября 2012, 00:05 # 0
            Спасибо!
            1. Алексей 14 ноября 2012, 10:00 # 0
              А почему
              $resource = $modx->event->params['resource'];

              ?

              Если открыть документацию rtfm.modx.com/display/revolution20/OnDocFormSave, то в Event Parameters мы видим resource, зачем его еще раз вытаскивать?
              1. Василий Наумкин 14 ноября 2012, 10:04 # 0
                А что, по вашему есть Event Parameters?

                По-моему, это массив $modx->event->params, из которого я и получаю ресурс.
                Если я не прав — покажите, как надо.
                1. Алексей 14 ноября 2012, 10:06 # 0
                  Ну я так понял, глядя на пример ниже по той же ссылке, что переменная $resource сразу доступна, как и $mode и $id.
                  1. Василий Наумкин 14 ноября 2012, 10:15 # 0
                    А я, глядя на исходник метода modX::invokeEvent(), понял, что нет.
                    1. Алексей 14 ноября 2012, 10:24 # 0
                      Ну как же, ведь передаются параметры:

                      https://github.com/modxcms/revolution/blob/release-2.2/core/model/modx/processors/resource/create.class.php#L566

                      в параметр $params:
                      public function invokeEvent($eventName, array $params= array ())
                      1. Василий Наумкин 14 ноября 2012, 10:30 # 0
                        Ну так я их и беру из $modx->event->params;, куда они передаются.

                        Кто, где, зачем и как выставляет $resource (и будет ли всегда выставлять, в дальнейших версиях) — мне неведомо. 100% я вижу одно — параметры, переданные для плагина, находятся вот тут: $modx->event->params.

                        Нравится брать их в $resource — вперед, никто вроде не мешает.

                        1. Василий Наумкин 20 ноября 2012, 19:09 # 0
                          Прислушался к вашему совету — убрал лишнее присвоение.

                          Спасибо!
                2. Peter Zenin 20 ноября 2012, 18:45 # 0
                  Вместо:
                  $key = $resource->get('context_key') . '/resources/' . $resource->get('id');

                  можно вот так:
                  $key = $resource->getCacheKey();

                  Спасибо за заметку, долго мучался пока не нашел эту вашу запись.
                  Да и вообще спасибо за все остальное!
                  1. Василий Наумкин 20 ноября 2012, 18:52 # 0
                    Ага, попробуйте проделать это в менеджере, getCacheKey() вернет вам 'mgr/resource/15'.

                    Сегодня придумал красивее:
                    $resource->_contextKey = $resource->context_key;
                    $key = $resource->getCacheKey();

                    1. Peter Zenin 20 ноября 2012, 19:18 # 0
                      Ясно. А мне просто хотелось очистить кеш из сниппета (точнее из хука formit), только одного конкретного ресурса.
                      Раньше чистил через clearCache, там просто было. но он deprecated теперь.
                      Везде искал — нет примеров, только вот этот, ваш. (как-то криво на вы общаться)
                      Вот для себя составил формулу, сохраню тут в комментах себе на будущее :-):
                      $key = $docObj->getCacheKey(); // $docObj - объект ресурса, кеш которого надо почистить
                      $cache = $modx->cacheManager->getCacheProvider($modx->getOption('cache_resource_key', null, 'resource'));
                      $cache->delete($key, array('deleteTop' => true));
                      $cache->delete($key);
                      
                      1. Василий Наумкин 20 ноября 2012, 19:45 # 0
                        Да можно «на ты», я не старый.

                        А рецепт я взял с официального форума, только пришлось поразбираться с контекстами. Очень надеюсь, что ни примут мой коммит и можно будет тупо
                        $resource->clearCache();
                        1. Peter Zenin 20 ноября 2012, 22:25 # 0
                          Да, только clearCache они отменяют. Сам интуитивно пробовал $resource->refresh() но не прокатило.
                  2. Noname Андрей 28 ноября 2012, 17:32 # 0
                    Василий, здравствуйте! У меня вопрос по этому полезному плагину.
                    Под какую он версию modx и что значит убирает галочку «Очистить кэш»? Имеется в виду, что он это делает в процессе сохранения документа или он убирает ее у всех документов в панели редактирования?
                    Дело в том, что этот плагин у меня не хочет работать. Сделал все как сказано в описании. Извините за такие вопросы, я только начал изучать эту cms.
                    Заранее спасибо!
                    1. Василий Наумкин 28 ноября 2012, 18:28 # 0
                      Я работаю только с MODX Revolution и на этом сайте мы говорим только про него.
                      Данный плагин проверялся на версии 2.2.5.

                      Он действует в 2 этапа: убирает галочку «Очистить кэш» при редактировании документа в админке, чтобы не обновлять кэш всех ресурсов, а потом при сохранении удаляет кэш текущей страницы.

                      Если вы только начинаете работать с MODX — Зачем вам такие вещи? Разбирайтесь сначала, не надо на кэширование сразу переходить.
                      1. Noname Андрей 28 ноября 2012, 21:49 # 0
                        Спасибо за камент. К нам приходят разноплановые задачи, в этот раз пришла задача с modx, тормоза и прочее. Этот плагин весьма кстати пришелся. Спасибо. Заставить бы его только работать.
                        1. Noname Андрей 29 ноября 2012, 13:27 # 0
                          Заработало. У вас в коде указано событие OnBeforeDocFormSave', а ниже в описании OnDocFormSave
                      2. Олег Максименко 04 апреля 2013, 11:48 # 0
                        Заметил интересный момент.
                        С этим плагином начинает неконкретно работать авто публикация ресурсов. Так как весь кэш при сохранении ресурса не чистится, соответственно и не обновляется auto_publish в кеше (в нем хранится unixtime ближнего готовящегося к публикации ресурса).

                        Решение:
                        Добавить к событию OnDocFormSave:

                        $contexts = array();
                        $query = $modx->newQuery('modContext');
                        $query->select($modx->escape('key'));
                        if ($query->prepare() && $query->stmt->execute()) {
                        	$contexts = $query->stmt->fetchAll(PDO::FETCH_COLUMN);
                        }
                        $modx->cacheManager->autoPublish(array_diff($contexts, array('mgr')));
                        
                        1. Давид Мовсесян 03 апреля 2014, 09:35 # 0
                          а вот как сделать так, чтобы при изменении любого документа на сайте или публикации нового документа чистился кеш только главной страницы? у меня просто на главной несколько новостных лент из разных контейнеров, снипеты вызываю кешированными, иначе тормоза.
                          1. Alexandr 16 мая 2014, 10:55 # 0
                            А вот у меня сайт обновляется по cron ежеминутно. Каждую минуту выгружаются новые данные и корректируются старые записи, т.е. файл с измененными данными отправляется на сервер по ftp, там скриптом вносятся изменения в БД, но для того, чтобы обновления были видны на сайте необходимо обновить кэш. И если запускать очистку всего кэша — то получается слишком долго.

                            Как в таком случае делается очистка кэша конкретного измененного ресурса,
                            1. Василий Наумкин 16 мая 2014, 11:35 # 0
                              Смотри методы в Tickets — bezumkin.ru/sections/components/396/
                            2. valentink2410 17 октября 2014, 12:15 # 0
                              Василий, подскажи пожалуйста, как запретить чистить весь кэш при удалении и восстановлении нового документа в админке modx revo 2.14, заранее спасибо
                              Добавление новых комментариев отключено.