Всем привет! У каждой записи в моем блоге есть метаинформация, где присутствует цифра с глазиком — это общее количество просмотров записи. Получается эта информация из плагина 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 события необходимо выключить и включить плагин.