Многие на нагруженных проектах на WordPress используют плагин WP Super Cache чтобы снизить нагрузку на сервер. Плагин создает статичные html странички и отдает их пользователю без обращения к php. Можно настроить и отдачу этих статичных страничек через nginx.

Как работает WP SuperCache

Статичные страницы имеет задаваемые параметры в виде срока жизни страницы (Cache Timeout ) и времени сбора мусора (Scheduler ). Процедура выглядит таким образом – при первом обращении пользователя к странице она собирается с помощью php, сегенеренная страница отдается пользователю и сохраняется, а следующий пользователь получает её уже из кеша WP Super Cache. Страница в кеше обновляется в зависимости от параметров срока жизни страницы (Cache Timeout ) / времени сбора мусора (Scheduler ). Так же можно настроить, что страница поста будет обновляться при добавлении комментария.

P.S. В версии WP Super Cache 1.0 на WordPress 3.x.x бывает что страница не обновляется при добавлении комментария. Автор баг признал, порекомендовал скачать девелоперскую версию, ну и в следующей версии баг обещал исправить. В девелоперской версии все работает.

И всё бы хорошо. Задавай сроки жизни страниц подольше, обновляй кеш с настройкой «Clear all cache files when a post or page is published or updated». Если стоят какие то виджеты – задавай нужные параметры обновления. Но неожиданная проблема обнаружилась с плагином рейтингов WP Postratings.

Суть проблемы связки WP SuperCache и WP PostRatings

Допустим заходит пользователь на страницу которой ещё нет в кеше, на ней установлен вывод значений WP Postratings. Если это страница поста, то блок WP Postratings 1 штука, если индексная страница архива, категории или тому подобное, то этих блоков может быть несколько ( или не быть вообще, тут уж как кто любит ). Так вот допустим человек зашел, проголосовал, обновил страницу, а его голос не засчитался. Человек жмет проголосовать ещё раз, а postratings ему говорит что вы уже проголосовали. Человек в недоумении. Причем заметьте с случае с комментированием такого не происходит. Если человек оставил коммент и обновил страницу, то он увидит сраницу уже со своим комментом. Что же не так.

Когда человек зашел впервые на страницу, страница была собрана и сохранена в кеше. Тогда он ещё не проголосовал в postratings. Страница сохранена без учета его оценки. Когда он нажал на звездочки postratings – его голос через javascript был учтен. Но страница в кеше обновлена не была. Поэтому обновив страницу он получит её из кеша, когда он её ещё не оценил.


Почем такого не происходит когда человек оставляет коммент?
Потому что WP Super Cache отлавливает событие комментирования и удаляет пост из кеша. Следующий пользователь при обращении генерит новый кеш страницы с новым комментарием.

Так что же нам делать со связкой WP Super Cache и WP Postratings, как заставить их работать вместе.

В сети есть один вариант. В принципе он одобрен автором WP Super Cache. Обсуждали его здесь . Идея этой модификации в том что оценка получается не при генерации странице, а через AJAX. То есть пользователь при обращении к странице с модулем WP Postratings получает кеш страницы из WP SuperCache, а оценку получает через AJAX, который в свою очередь обращается к wp-postraings.php, который в свою очередь обращается к базе за оценкой этого поста. Таким образом, если у человека включен JavaScript то он всегда будет получать актуальную оценку. Всё вроде бы хорошо и работает. Но!

Предположим главную страницу блога, блок со звездочками WP PostRatings выводится под каждым анонсом статьи ( это довольно эффективно, поверьте ), допустим их 10 штук. Каждый такой модуль получает через AJAX свою оценку, таким образом за одно обращение к главной странице ( не зависимо в кеше SuperCache она или нет ), мы получаем 10 обращений к MySQL, PHP. Предположим, что главную посещают 10000 хостов. Итого 10 000 обращений к MySQL, PHP. По статистике CTR WP Postratings порядка 2-5%, то есть 95 000 обращений в холостую. 95% посетителей не нужен AJAX в WP PostRatings, 95% хостов были бы вполне удовлетворены страничкой из кеша WP SuperCache. Так зачем напрягать сервак, зачем заставлять юзеров ждать прогрузки оценок. Давайте будем людям отдавать статичные странички из WP SuperCache. И обновлять их при новой оценке.

Как же это сделать. Если без заморочек – легко.

Отлавливаем событие добавления новой оценки. Обновляем страничку данного поста в кеше, и страничку, откуда была произведена оценка.
При нажатии на звездочку AJAX обращается к файлу плагина wp-postratings.php  , к функции process_ratings()  , в ней оценивается правомочность оценки пользователем статьи. Давайте после строки


добавим нашу функцию azz_post_rated($post_id, $_SERVER['HTTP_REFERER']);  Собственно ID оцениваемого поста и адрес странички с которого была произведена оценка. А в файликt functions.php  нашей темы создадим две функции:


Как то так. Код очень сырой. Но работает. Кому надо сам допилит. У меня в таком виде работает. При обновлении оценки WP PostRatings удаляется кеш страницы оцениваемого поста и кеш странички откуда была произведена оценка.

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