Всем привет! У каждой записи в моем блоге есть метаинформация, где присутствует цифра с глазиком — это общее количество просмотров записи. Получается эта информация из плагина Jetpack.
Попытка №1 — решение в лоб с кешированием
Получение количества просмотров работает чрезвычайно медленно. Например, некоторые мои страницы при работе напрямую с плагином загружались аж ПЯТЬДЕСЯТ ТРИ (!!!) секунды. Поэтому в один прекрасный день я выключил этот функционал. Код был такой (functions.php
), не используйте его, он здесь только для истории:
# Используем класс WPCOM_Stats из Jetpack
use Automattic\Jetpack\Stats\WPCOM_Stats;
# Метод получения количества просмотров с кэшированием
function get_post_views($post_id) {
# Ключ кэша "wp_cached_counter_номер_поста"
$cache_key = 'wp_cached_counter_' . $post_id;
# Получим значение кэша по ключу
$counter = get_transient($cache_key);
# Если значения нет, значит создадим
if (false == $counter) {
# Объект класса для работы со статистикой Jetpack
$wp_stats = new WPCOM_Stats();
# Получим статистику просмотров для $post_id и преобразуем её в объект (тут может пройти до ДЕСЯТИ секунд)
$stats = $wp_stats->convert_stats_array_to_object($wp_stats->get_post_views($post_id));
# Количество просмотров
$counter = intval($stats->views);
# Сохраним в кэше на час
set_transient($cache_key, $counter, HOUR_IN_SECONDS);
}
return $counter;
}
# Печатаем количество просмотров поста
function print_view_counter() {
# Получим значение
$counter = get_post_views(get_the_ID());
# Нулевые счётчики не выводим
if ($counter) {
return;
}
# Если больше тысячи, выведем количество тысяч с суффиксом K. То есть вместо 6404 будет 6K
if (intval($counter) > 1000) {
printf('<span class="view" title="%s">%sK</span>', $counter, intdiv($counter, 1000));
}
else {
printf('<span class="view">%s</span>', $counter);
}
}
Затем вставляем в любом месте темы код:
<?php print_view_counter(); ?>
и получаем цифру просмотров.
Спустя какое-то время я увидел, что страницы грузятся безбожно долго, особенно страницы с категориями или тегами. Некоторые грузились по минуте, потому что запрос количества просмотров идёт с сайта stats.wp.com и иногда доходит до ДЕСЯТИ СЕКУНД на запрос.
Попытка №2 — использование WPCron без кеширования
В итоге я решил запускать обновление счётчиков периодически по крону, записывать/получать их значения с помощью update_post_meta
и get_post_meta
соответственно в поле _post_counter
. В моём самописном плагине я ежедневно обновляю информацию:
# Используем Jetpack WPCOM_Stats
use Automattic\Jetpack\Stats\WPCOM_Stats;
# Метод получения счётчика без кеширования, возвращает цифру
function b2k_get_post_counter($wp_stats, $post_id) {
$stats = $wp_stats->convert_stats_array_to_object($wp_stats->get_post_views($post_id));
return intval($stats->views);
}
# Обновление счётчиков у всех страниц в блоге
function b2k_update_all_counters() {
$posts = get_posts(
array(
'post_type' => 'any',
'posts_per_page' => -1,
'post_status' => 'publish'
)
);
# Создадим один раз объект для запроса статистики
$wp_stats = new WPCOM_Stats();
# Для каждой страницы
foreach ($posts as $post) {
# Запрашиваем счётчик
$counter = b2k_get_post_counter($wp_stats, $post->ID);
# Записываем его в мета поле с именем _post_counter каждой странице
update_post_meta($post->ID, '_post_counter', $counter);
}
}
# Создаём событие b2k_update_counters_event
add_action('b2k_update_counters_event', 'b2k_update_all_counters');
# Во время активации плагина
function b2k_cron_activation() {
# Убираем хук b2k_update_counters_event
wp_clear_scheduled_hook('b2k_update_counters_event');
# Добавляем ежедневный запуск события b2k_update_counters_event
wp_schedule_event(time(), 'daily', 'b2k_update_counters_event');
}
register_activation_hook(__FILE__, 'b2k_cron_activation');
# Во время деактивации плагина
function b2k_cron_deactivation() {
# Удаляем хук
wp_clear_scheduled_hook('b2k_update_counters_event');
}
register_deactivation_hook(__FILE__, 'b2k_cron_deactivation');
В теме я просто получаю значение поля:
function print_view_counter() {
# Получить значение мета поля _post_counter, всегда строка
$counter = get_post_meta($post_id, "_post_counter", true);
# Если счётчика нет, значит ноль
if (!$counter) {
$counter = 0;
}
else {
# Иначе нам нужна цифра
$counter = intval($counter);
}
# Если больше тысячи, выведем количество тысяч с суффиксом K. То есть вместо 6404 будет 6K
if ($counter > 1000) {
printf('<span class="view" title="%s">%sK</span>', $counter, intdiv($counter, 1000));
}
else {
printf('<span class="view">%s</span>', $counter);
}
}
В вычислении скорости загрузи меня выручил плагин Query Monitor. Для работы кода обязателен плагин Jetpack с включенным модулем Stats. Для первоначальной установки Cron события необходимо выключить и включить плагин.