WP Cron – всё про планировщик задач WordPress

WP-Cron – это планировщик в WordPress, используемый для запуска периодически выполняемых задач, либо задач, которые должны быть запущены в определённое время.

Также важно упомянуть, что задачи WP-Cron не запускаются автоматически, просто при каждой загрузке страницы происходит сопоставление всех запланированных задач с текущим временем и, если время выполнения уже наступило, задача будет запущена. Это также значит, что если у вас запланирована задача на скажем 5:31 и если посещаемость вашего сайта не очень высокая, то задача скорее всего будет выполнена позднее указанного времени.

Также рекомендую свой видеокурс по созданию темы WordPress на основе готовой вёрстки.

Примеры работы WP-Cron в ядре WordPress

Ниже я приведу таблицу, в которой перечислены события WP-Cron, запланированные непосредственно в ядре WordPress.

Первая колонка таблицы – это хук события, ниже в этом уроке мы научимся использовать его для создания своих событий или для снятия событий из расписания.

Хук событияОписание
wp_version_checkПроверка обновлений ядра WordPress, дважды в день.
wp_update_pluginsПроверка обновлений плагинов, дважды в день.
wp_update_themesПроверка обновлений тем, дважды в день.
wp_scheduled_deleteОчистка корзины, для постов и комментариев, раз в день.
delete_expired_transientsОчистка транзитов раз в день.
wp_scheduled_auto_draft_deleteУдаление авто-черновиков (auto-draft) раз в день.
wp_privacy_delete_old_export_filesУдаление старых файлов экспорта раз в день.
wp_site_health_scheduled_checkПроверка и обновление статуса здоровья сайта раз в неделю.
wp_https_detectionПроверка, поддерживается ли на сайте HTTPS, дважды в день.

WP-Cron — это очень просто, однако я помню то время, когда боялся к нему подступиться. Просто читайте эту статью последовательно и сразу же выполняйте данные здесь примеры и этого будет достаточно, чтобы освоить планировщик задач в WordPress.

Как проверить, что WP-Cron работает на сайте?

Обычно на сайтах WordPress с планировщиком всё окей, однако всё же бывают случаи, когда он не работает. Поэтому, прежде чем перейти к примерам, давайте убедимся, что с ним всё окей.

Используя «Здоровье сайта»

Начиная с версии WordPress 5.2, когда появилась функция Здоровье сайта, это стало делать очень легко – достаточно лишь перейти в Инструменты > Здоровье сайта и проверить, есть ли там рекомендация «Запланированное задание пропущено».

Проверка работы WP-Cron в Здоровье сайта

Используя запланированную публикацию записи

Если вдруг у вас стоит старая версия WordPress и вы не можете проверить работу планировщика в Здоровье сайта, то достаточно создать пост и в качестве даты публикации установить время в будущем, ну и понятное дело, чтобы долго ждать не пришлось, можно поставить время на 2 или 5 минут позже текущего.

Создание запланированной публикации записи

Если WP_Cron работает на вашем сайте, то пост просто опубликуется через пару минут, а если не работает, то вот что вы получите:

Запланированная публикация записи пропущена

Как починить WP_Cron?

Итак, что же делать, если планировщик отказывается работать на вашем сайте? Сейчас я не буду слишком подробно на этом останавливаться, но дам несколько базовых советов, которые возможно помогут вам разобраться с проблемой.

  1. Прежде всего попробуйте открыть файл wp-config.php и проверьте, нет ли там строчки, отключающей CRON define('DISABLE_WP_CRON', true);. Если есть, попробуйте её просто удалить и посмотрите, что получится.
  2. Если в wp-config.php всё в порядке, то… сами добавим эту строку… если быть точным, то мы попробуем подключить альтернативную конфигурацию планировщика, для это в wp-config.php помещаем следующий код:
define( 'DISABLE_WP_CRON', true );
define( 'ALTERNATE_WP_CRON', true );
  1. Если не помогло, то вы можете попробовать использовать системный планировщик в вашей хостинг-панели. Опять-таки нужно отключить (хотя он и так не работает) виртуальный WP_Cron строчкой:
define( 'DISABLE_WP_CRON', true );
  1. В хостинг-панели (например cPanel) вам нужно найти соответствующий инструмент планировщика. Заходим в него и в поле «Команда для выполнения» (или что-то типо того) указываем URL вашего файла wp-cron.php на сайте, а если быть точным, то:
wget -O /dev/null http://misha.agency/wp-cron.php?doing_wp_cron

Всё ещё ничего не получается? Тогда рекомендую попробовать разобраться с супортом хостинга, если не могут помочь, но возможно следует рассмотреть переезд на другой хостинг, например на мой. Дело в том, что проблемы с виртуальным WP_Cron – это проблемы именно с сервером, а значит супорт вам обязан помочь.

Как отключить WP_Cron?

В целом в предыдущем шаге я уже упомянул, как это сделать, но расскажу ещё раз. Чтобы отключить планироващик WP-Cron на вашем сайте, зайдите в файл wp-config.php, который лежит в корне вашего сайта и поместите туда строчку

define( 'DISABLE_WP_CRON', true );

Но не в самый конец файла, а до require_once ABSPATH . 'wp-settings.php';.

Создание запланированной задачи

Задача, которая выполнится один раз в определённое время

Для этих целей в WordPress существует функция wp_schedule_single_event().

wp_schedule_single_event( time() + 60, 'misha_action_hook' );
  • В первом параметре мы указываем время в UNIX-формате, в данном случае time() — текущее время, +60секунд, это значит, что событие запланируется на выполнение ровно через минуту после запуска функции.
  • Второй параметр – это название хука WordPress, который запустится через минуту. Про хуки и фильтры я обязательно подробно напишу отдельную статью. А пока что постараюсь просто подробно описать на примерах.

Окей, начало у нас есть, теперь вопрос — куда это вставить? Просто в functions.php не получится, ведь тогда событие будет пытаться запланироваться каждый раз при загрузке/обновлении любой страницы сайта.

Поэтому код непосредственно с запуском этой функции лучше всего добавлять в обработчики форм например. Форма отправлена – событие запланировано. Всё просто.

Однако я воспользуюсь тем, что при смене темы WordPress на страницу передаётся параметр GET activated, равный true — в таком случае я смогу вставить код прямо в functions.php в следующем виде:

if( 'true' == $_GET[ 'activated' ] ) {
	wp_schedule_single_event( time() + 60, 'misha_action_hook' );
}

Это означает, что как только переключиться на текущую тему, событие запланируется.

Хорошо, что же теперь делать с misha_action_hook? Повторяю — это не функция! Просто очень частой ошибкой бывает, что люди начинают писать функцию function misha_action_hook( лалала ) — это неправильно, а правильно будет так:

// вот он хук и мы вешаем на него произвольную функцию
add_action( 'misha_action_hook', 'test' );
// конечно можно повесить и несколько функций на один хук!
 
function test() {
	// банально поменяю емайл администратора на сайте, проще всего протестировать
	update_option( 'admin_email', 'misha@truemisha.ru' );
}

Незнакомая функция? Читайте подробнее про update_option().

Вставляем всё это пошагово в functions.php, переключаемся сначала на какую-нибудь левую тему, а потом обратно на текущую, замечаем минуту и потом смотрим емайл в настройках.

Для вашего удобства вот полностью готовый код из примера.

if( 'true' == $_GET[ 'activated' ] ) {
	wp_schedule_single_event( time() + 60, 'misha_action_hook' );
}
 
add_action( 'misha_action_hook', 'test' );
 
function test() {
	update_option( 'admin_email', 'misha@truemisha.ru' );
}

И напоследок — у функции wp_schedule_single_event() есть ещё один, третий аргумент, который содержит параметры, передаваемые в хук, и тут я предлагаю вам два варианта — вы можете перейти по ссылке на функцию, чтобы почитать о ней подробнее там, либо переходите к следующему примеру, хоть он уже и про другую функцию, но параметр с аргументами работает у них одинаково.

Планируем задачу, которая будет выполняться регулярно через определенные интервалы времени

В этом нам поможет функция wp_schedule_event().

wp_schedule_event( time(), 'hourly', 'misha_hook_1', array( 'no-reply@misha.agency', 'Тест тема', 'Тест сообщение' ) );
  • В первом параметре указывается время первого выполнения задачи, при помощи функции time() я указал текущее время, то есть тот самый момент, когда функция будет запущена. Напоминаю, что время в UNIX-формате.
  • Второй параметр — это один из предопределенных вордпрессом интервалов времени, hourly — раз в час, twicedaily — дважды в день, daily — раз в день. О том, как задать собственный интервал, читайте ниже.
  • Третий параметр — это название хука, я надеюсь, что в предыдущем примере я хоть немного пролил на это свет и теперь хоть немного, но понятно, что это значит.
  • А вот четвертый — это одномерный массив из параметров, передаваемых в хук, в данном случае misha_hook_1.

Куда вставлять?

Тут я хочу обратить ваше внимание, что сколько раз вы запустите функцию wp_schedule_event(), то столько раз и запланируется повторяющееся событие!

Вне зависимости от того, куда вы её вставите, сделайте проверку, что точно такая же задача уже не запланирована. В этом вам поможет функция wp_next_scheduled().

$parametri = array( 'no-reply@misha.agency', 'Тест тема', 'Тест сообщение' );
 
// если ещё не запланировано - планируем
if( ! wp_next_scheduled( 'misha_hook_1', $parametri ) ) {
	wp_schedule_event( time(), 'hourly', 'misha_hook_1', $parametri );
}

Событие считается уникальным, если хотя бы один из передаваемых параметров отличается.

Ну а дальше — функция и хук. Код будет ежечасно отправлять мне сообщения с сайта.

// вот он хук и мы вешаем на него произвольную функцию, цифра 3 - количество передаваемых параметров
add_action( 'misha_hook_1', 'misha_send', 10, 3 );
// конечно можно повесить и несколько функций на один хук!
 
function misha_send( $to, $subject, $msg ) {
	// отправляем емайл каждый час
	wp_mail( $to, $subject, $msg );
}

Для отправки писем я использую стандартную функцию WordPress — wp_mail(). Обратите внимание, что необязательно создавать функцию misha_send(), а можно сразу повесить wp_mail() на хук.

Ну и конечно же готовый код для вашего удобства.

$parametri = array( 'no-reply@misha.agency', 'Тест тема', 'Тест сообщение' );
 
// если ещё не запланировано - планируем
if( ! wp_next_scheduled( 'misha_hook_1', $parametri ) ) {
	wp_schedule_event( time(), 'hourly', 'misha_hook_1', $parametri );
}
 
add_action( 'misha_hook_1', 'misha_send', 10, 3 );
 
function misha_send( $to, $subject, $msg ) {
	wp_mail( $to, $subject, $msg );
}

Как задать свой собственный интервал?

По умолчанию в WordPress 4 зарегистрированных интервала времени:

$schedules = array(
	'hourly' => array( // каждый час
		'interval' => HOUR_IN_SECONDS,
		'display'  => __( 'Once Hourly' ),
	),
	'twicedaily' => array( // каждые 12 часов
		'interval' => 12 * HOUR_IN_SECONDS,
		'display'  => __( 'Twice Daily' ),
	),
	'daily' => array( // каждые 24 часа, раз в день
		'interval' => DAY_IN_SECONDS,
		'display'  => __( 'Once Daily' ),
	),
	'weekly' => array( // раз в неделю
		'interval' => WEEK_IN_SECONDS,
		'display'  => __( 'Once Weekly' ),
	),
);

Кстати, в этом коде мы видим временные константы в WordPress, про них я отдельно рассказывал в этом уроке.

Если вас не устраивают стандартные вордпрессовские интервалы времени, вы с лёгкостью можете добавить в этот массив свой собственный.

Делается это предельно просто при помощи следующего хука:

add_filter( 'cron_schedules', 'true_moi_interval'); 
 
function true_moi_interval( $raspisanie ) {
	// $raspisanie - это массив, состоящий из всех зарегистрированных интервалов
	// наша задача - добавить в него свой собственный интервал, к примеру пусть будет 3 минуты
	$raspisanie[ 'kajd_3_min' ] = array(
		'interval' => 180, // в одной минуте 60 секунд, в трёх минутах - 180
		'display' => 'Каждые три минуты' // отображаемое имя
	);
	return $raspisanie;
}

Если не знаете, куда вставлять этот код, читайте.

Всё, интервал зарегистрирован, теперь можно использовать его имя kajd_3_min при планировке повторяющихся событий.

Просмотр запланированных задач

Делается это довольно просто двумя способами — либо через плагин, либо через код. Если вам часто приходится мониторить, то конечно лучше и удобнее воспользоваться плагином, но обо всём по порядку.

Просмотр и отладка через код

Cron-задачи хранятся в виде массива прямо в таблице wp_options базы данных. А значит их можно получить при помощи функции get_option(). И вот как это делается.

// получаем все задачи из базы данных
$cron_zadachi = get_option( 'cron' );
 
// можно использовать функции print_r() или var_dump() для вывода всех задач
echo '<pre>';
print_r( $cron_zadachi );
exit;

Или же при помощи функции _get_cron_array().

echo '<pre>';
print_r( _get_cron_array() );
exit;

В результате они выведутся примерно в таком формате:

Выводим информацию о запланированных задачах через код.

При помощи плагина Advanced Cron Manager

Зная из предыдущей главы, как выводятся задачи, вы теперь с лёгкостью и сами сможете написать плагин для мониторинга, а я поделюсь с вами тем плагином, который использую сам и в общем-то пока он меня устраивает — бесплатный Advanced Cron Manager (добавляйте прямо через админку). Если вы знаете плагины получше, прошу поделиться в комментариях 🙂

Заходим в Инструменты > Список задач планировщика и все задачи перед нами:

Мониторим Cron-задачи при помощи плагина WordPress Advanced Cron Manager

Как удалить запланированную задачу из расписания?

Удаление задач происходит при помощи одной из двух функций — wp_clear_scheduled_hook() или wp_unschedule_event(), отличие второй от первой заключается в том, что она может удалить более конкретную задачу, если вам интересны подробности, переходите по ссылкам и читайте описания этих функций.

Что же касается наших примеров 1 и 2, для удаления этих событий нам подойдёт любая из них, поэтому давайте первое событие с хуком misha_hook_1 удалим функцией wp_clear_scheduled_hook(), а второе с хуком misha_action_hook функцией wp_unschedule_event().

// удаляем первое событие
wp_clear_scheduled_hook( 'misha_hook_1', array( 'no-reply@misha.agency', 'Тест тема', 'Тест сообщение') );
 
// удаляем второе событие
wp_unschedule_event( wp_next_scheduled( 'misha_action_hook' ), 'misha_action_hook' );

Первый параметр функции wp_unschedule_event() — это штамп времени, который вы можете получить при помощи wp_next_scheduled(), либо глянуть его при выводе всех задач через код, тут это будет 1469678041.

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Если вам нужна помощь с сайтом или разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда будем рады вам помочь!

Комментарии — 2

Оставить комментарий

Если вы хотите добавить код, не забудьте обернуть его в <pre lang="php"></pre>, если же код – меньше одной строчки, то можно и в <code></code>.