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

Постоянно задают вопросы "а как при сохранении чистить кэш не всего сайта, а только обновляемого ресурса?".
А вот так:
<?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 в админке.

27 комментариев

Спасибо большое!
Антон Слободчук
Странно, что разработчики MODX не добавили эту функциональность по умолчанию. Я думал, что это связано с тем, что «куски» кэша ресурса могут хранится не только в /resources/id-ресурса.
Иван Брежнев
Нет, они не добавили потому что ресурс может быть использован в списках, и при обновлении одного ресурса список останется со старыми данными
Иван Брежнев
Просто нужно заранее предусмотреть где и что вам нужно чистить
Василий уже писал об этом. Да, из-за возможных хитрых взаимодействий ресурсов приходится чистить весь кэш. http://modx.com/blog/2012/10/29/optimization-with-getcache-and-custom-cache-partitions/
Alexander Orel
Спасибо!
Алексей
А почему
$resource = $modx->event->params['resource'];
?
Если открыть документацию rtfm.modx.com/display/revolution20/OnDocFormSave, то в Event Parameters мы видим resource, зачем его еще раз вытаскивать?
Василий Наумкин
А что, по вашему есть Event Parameters?
По-моему, это массив $modx->event->params, из которого я и получаю ресурс.
Если я не прав — покажите, как надо.
Алексей
Ну я так понял, глядя на пример ниже по той же ссылке, что переменная $resource сразу доступна, как и $mode и $id.
Василий Наумкин
А я, глядя на исходник метода modX::invokeEvent(), понял, что нет.
Алексей
Ну как же, ведь передаются параметры:
в параметр $params:
public function invokeEvent($eventName, array $params= array ())
Василий Наумкин
Ну так я их и беру из $modx->event->params;, куда они передаются.
Кто, где, зачем и как выставляет $resource (и будет ли всегда выставлять, в дальнейших версиях) — мне неведомо. 100% я вижу одно — параметры, переданные для плагина, находятся вот тут: $modx->event->params.
Нравится брать их в $resource — вперед, никто вроде не мешает.
Василий Наумкин
Прислушался к вашему совету — убрал лишнее присвоение.
Спасибо!
Вместо:
$key = $resource->get('context_key') . '/resources/' . $resource->get('id');
можно вот так:
$key = $resource->getCacheKey();
Спасибо за заметку, долго мучался пока не нашел эту вашу запись.
Да и вообще спасибо за все остальное!
Василий Наумкин
Ага, попробуйте проделать это в менеджере, getCacheKey() вернет вам 'mgr/resource/15'.
$resource->_contextKey = $resource->context_key;
$key = $resource->getCacheKey();
Ясно. А мне просто хотелось очистить кеш из сниппета (точнее из хука 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);
Василий Наумкин
Да можно «на ты», я не старый.
А рецепт я взял с официального форума, только пришлось поразбираться с контекстами. Очень надеюсь, что ни примут мой коммит и можно будет тупо
$resource->clearCache();
Да, только clearCache они отменяют. Сам интуитивно пробовал $resource->refresh() но не прокатило.
Noname Андрей
Василий, здравствуйте! У меня вопрос по этому полезному плагину.
Под какую он версию modx и что значит убирает галочку «Очистить кэш»? Имеется в виду, что он это делает в процессе сохранения документа или он убирает ее у всех документов в панели редактирования?
Дело в том, что этот плагин у меня не хочет работать. Сделал все как сказано в описании. Извините за такие вопросы, я только начал изучать эту cms.
Заранее спасибо!
Василий Наумкин
Я работаю только с MODX Revolution и на этом сайте мы говорим только про него.
Данный плагин проверялся на версии 2.2.5.
Он действует в 2 этапа: убирает галочку «Очистить кэш» при редактировании документа в админке, чтобы не обновлять кэш всех ресурсов, а потом при сохранении удаляет кэш текущей страницы.
Если вы только начинаете работать с MODX — Зачем вам такие вещи? Разбирайтесь сначала, не надо на кэширование сразу переходить.
Noname Андрей
Спасибо за камент. К нам приходят разноплановые задачи, в этот раз пришла задача с modx, тормоза и прочее. Этот плагин весьма кстати пришелся. Спасибо. Заставить бы его только работать.
Noname Андрей
Заработало. У вас в коде указано событие OnBeforeDocFormSave', а ниже в описании OnDocFormSave
Олег Максименко
Заметил интересный момент. С этим плагином начинает неконкретно работать авто публикация ресурсов. Так как весь кэш при сохранении ресурса не чистится, соответственно и не обновляется 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')));
Давид Мовсесян
а вот как сделать так, чтобы при изменении любого документа на сайте или публикации нового документа чистился кеш только главной страницы? у меня просто на главной несколько новостных лент из разных контейнеров, снипеты вызываю кешированными, иначе тормоза.
А вот у меня сайт обновляется по cron ежеминутно. Каждую минуту выгружаются новые данные и корректируются старые записи, т.е. файл с измененными данными отправляется на сервер по ftp, там скриптом вносятся изменения в БД, но для того, чтобы обновления были видны на сайте необходимо обновить кэш. И если запускать очистку всего кэша - то получается слишком долго. Как в таком случае делается очистка кэша конкретного измененного ресурса,
Василий Наумкин
Смотри методы в Tickets - http://bezumkin.ru/sections/components/396/
Василий, подскажи пожалуйста, как запретить чистить весь кэш при удалении и восстановлении нового документа в админке modx revo 2.14, заранее спасибо
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
22.11.2024, 03:33:54
Спасибо!
inna
06.11.2024, 15:47:13
Да. Все работает. Спасибо.
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так. А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен. Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500 Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи. ...
Василий Наумкин
20.03.2024, 21:21:52
Volledig!
Андрей
14.03.2024, 13:47:10
Василий! Как всегда очень круто! Моё почтение!
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо! Извини, тупанул.
Василий Наумкин
22.01.2024, 07:43:20
Давай-давай!