Использование транзиентов и WP Cron для кэширования результата тяжеловесных операций WordPress
Продолжаем изучать возможности WordPress вместе с разработчиком We Wizards Константином Агафоновым.
На веб-сайтах часто возникают ситуации, когда необходимо отобразить таблицу или виджет, разметка и содержание которых вычисляются на основе данных из БД и требуют много ресурсов сервера на эту операцию. Например, заказчик попросил добавить многоуровневое меню категорий товаров магазина:
В меню должны отображаться только категории, в которых имеются товары в наличии в данный момент. Один из уровней меню — это отдельная от категорий таксономия товаров, то есть, необходимо фильтровать еще и значения отдельной таксономии по значению категории. Чтобы получить такую структуру данных, необходимо сделать очень много сложных запросов в БД магазина. Примерно по одному запросу на каждый пункт меню. Затем на основе получившегося дерева данных сгенерировать разметку меню. Это очень ресурсоемкий процесс, который нецелесообразно делать при загрузке каждой страницы сайта, потому что ожидание загрузки страницы посетителем может быть настолько большим, что превысит максимальное время работы скриптов на бэкенде, которое составляет от 30 секунд до нескольких минут.
Разберем один из подходов, который можно использовать при решении этой задачи — запуск ресурсоемкого процесса в фоне с помощью WP Cron и кэширование результатов c помощью транзиентов
Выделим ресурсоемкую задачу в отдельную функцию и повесим ее на кастомный хук:
add_action('build_catalog_menu_tree', 'build_catalog_menu_tree_callback');
function build_catalog_menu_tree_callback() {
// Построить меню категорий
$categories_tree_html = [здесь ресурсоемкий процесс, который анализирует наличие товаров, строит дерево меню и формирует разметку меню];
// И сохранить значение - здесь будем сохранять сформированную разметку
}
Транзиенты (transient) в WordPress — это функциональность, которая позволяет записывать произвольные значения в базу данных, привязывая их к произвольному ключу, и получать их обратно по этому же ключу. Записать значение можно следующей функцией:
set_transient( 'key', $value );
$value
может быть любого типа, в том числе массивом. В этом случае значение сериализуется перед записью в БД. Можно установить срок хранения в секундах. Для этого необходимо передать в функцию третий аргумент типа int
вот так:
set_transient( 'key', $value, $expiration );
В нашем случае будем сохранять разметку меню так:
// И сохранить значение
// записать его в транзиент
set_transient( 'catalog_menu_html', $categories_tree_html );
Теперь необходимо настроить фоновое выполнение ресурсоемкой функции по расписанию. Для этого в WordPress ecть механизм WP Cron, позволяющий запускать единичные задачи в фоне или настроить периодическое выполнение задачи раз в указанный интервал времени. В нашем случае код будет следующий:
add_action('init','schedule_build_catalog_menu');
function schedule_build_catalog_menu() {
// Проверить, не запланировано ли уже задание
if ( !wp_next_scheduled('build_catalog_menu_tree') ) {
wp_schedule_event(
// Начать с текущего момента
time(),
// Выполнять задачу раз в час
'hourly',
// Здесь указать кастомный хук, созданный ранее
'build_catalog_menu_tree'
);
}
}
Формирование меню в фоне и кэширование готово. Остается только выводить в нужном месте шаблона сайта значение соответствующего транзиента:
<?php echo get_transient( 'catalog_menu_html' ); ?>