WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

wp_schedule_event() WP 2.1

Создает многоразовую крон-задачу. Устанавливает хук, который будет вызываться каждый раз через указанный интервал времени.

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

Чтобы удалить имеющееся событие используйте wp_clear_scheduled_hook()

Основа для: wp_reschedule_event()
Хуки из функции
Возвращает

nul/false. null когда планирование завершено. false в случае неудачи.

Использование

wp_schedule_event( $timestamp, $recurrence, $hook, $args );
$timestamp(число) (обязательный)

Начальная метка времени, с которой хук начнет работать. Нужно указывать в формате UNIX (32165487).

WP cron использует время UTC/GMT, а не локальное. Используйте функцию time(), которая всегда в GMT в WP. current_time('timestamp') - это локальное время в WP.
По умолчанию: нет

$recurrence(строка) (обязательный)

Как часто должно повторяться действие. Допустимые значения ниже. Вы можете создать свой интервал используя фильтр cron_schedules из функции wp_get_schedules().

  • hourly - ежечасно;
  • twicedaily - дважды в день;
  • daily - ежедневно.

По умолчанию: нет

$hook(строка) (обязательный)
Название хука, который нужно выполнять.
По умолчанию: нет
$args(массив)
Аргументы, которые нужно передать в выполняемый хук.
По умолчанию: нет

Примеры

#1 Создаем крон задачу при активации плагина

Запланируем ежечасное действие для плагина. Для этого вызовем wp_schedule_event() при активации плагина (если делать не при активации, то мы получим множество запланированных событий!).

register_activation_hook(__FILE__, 'my_activation');
function my_activation() {
	// удалим на всякий случай все такие же задачи cron, чтобы добавить новые с "чистого листа"
	// это может понадобиться, если до этого подключалась такая же задача неправильно (без проверки что она уже есть)
	wp_clear_scheduled_hook( 'my_hourly_event' );

	// Проверим нет ли уже задачи с таким же хуком
	// этот пункт не нужен, потому что мы выше удалил все задачи...
	// if( ! wp_next_scheduled( 'my_hourly_event' ) ) 

	// добавим новую cron задачу
	wp_schedule_event( time(), 'hourly', 'my_hourly_event');
}

// Будет грамотно проверить выполняется ли крон, если нет - ничего не делаем
// Можно не проводить эту проверку, в принципе
if( defined('DOING_CRON') && DOING_CRON ){
	add_action('my_hourly_event', 'do_this_hourly');
	function do_this_hourly() {
		// делаем что-либо каждый час
	}
}

// При дезактивации плагина или в других случаях, обязательно нужно удалить ранее созданную задачу:
register_deactivation_hook( __FILE__, 'my_deactivation');
function my_deactivation() {
	wp_clear_scheduled_hook('my_hourly_event');
}

#2 Создаем крон задачу если её еще нет

Этот пример не полагается на активацию плагина (через директорию плагинов), вместо этого он добавляет событие, если его не существует:

// добавляем запланированный хук
add_action( 'wp', 'my_activation' );
function my_activation() {
	if( ! wp_next_scheduled( 'my_hourly_event' ) ) {
		wp_schedule_event( time(), 'hourly', 'my_hourly_event');
	}
}

// добавляем функцию к указанному хуку
add_action( 'my_hourly_event', 'do_this_hourly' );
function do_this_hourly() {
	// делаем что-либо каждый час
}

Удаляется задача так:

wp_clear_scheduled_hook( 'my_hourly_event' );

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

#3 Добавление нового интервала

Чтобы добавить новый интервал Cron в WordPress, используем фильтр cron_schedules.

Добавим интервал «5 минут» (делать что-либо каждые 5 минут):

// регистрируем 5минутный интервал
add_filter( 'cron_schedules', 'cron_add_five_min' );
function cron_add_five_min( $schedules ) {
	$schedules['five_min'] = array(
		'interval' => 60 * 5,
		'display' => 'Раз в 5 минут'
	);
	return $schedules;
}

// регистрируем событие
add_action( 'wp', 'my_activation' );
function my_activation() {
	if ( ! wp_next_scheduled( 'my_five_min_event' ) ) {
		wp_schedule_event( time(), 'five_min', 'my_five_min_event');
	}
}
// добавляем функцию к указанному хуку
add_action( 'my_five_min_event', 'do_every_five_min' );
function do_every_five_min() {
	// делаем что-либо каждые 5 минут
}

Константы WordPress, которые могут пригодится при создании крон интервала:

  • HOUR_IN_SECONDS - час в секундах - 60*60 = 3600
  • DAY_IN_SECONDS - день в секундах - 60*60*24 = 86400
  • WEEK_IN_SECONDS - неделя в секундах - 60*60*24*7 = 604800

#4 Еще пример создания крон задачи (рабочий пример)

Что делает пример: получает курс рубля по отношению к доллару и записывает результат в опции. Делается это всего 2 раза в сутки, для чего собственно и нужен крон. Далее, где нужно данные можно очень быстро получить из опции, куда они были записаны.

Получение данных валют работает на основе библиотеки PHP Simple HTML DOM Parse

// Cron
// Регистрируем расписание при активации плагина
register_activation_hook(__FILE__, 'activation_geting_course_dollar');
function activation_geting_course_dollar() {
	wp_clear_scheduled_hook( 'geting_course_dollar' );
	wp_schedule_event( time(), 'twicedaily', 'geting_course_dollar');
}

// Удаляем расписание при деактивации плагина
register_deactivation_hook( __FILE__, 'deactivation_geting_course_dollar');
function deactivation_geting_course_dollar() {
	wp_clear_scheduled_hook('geting_course_dollar');
}

// Проверка существования расписания во время работы плагина на всякий пожарный случай
if( ! wp_next_scheduled( 'geting_course_dollar' ) ) {  
	wp_schedule_event( time(), 'twicedaily', 'geting_course_dollar');  
}

// Хук и функция, которая будет выполняться по Крону
add_action( 'geting_course_dollar', 'get_real_course_dollar' );  
function get_real_course_dollar(){
	include 'inc/simple_html_dom.php';
	$html = file_get_html( 'https://news.yandex.ru/quotes/1.html' );
	$value = $html->find('.quote_current_yes', 0)->find('.quote__value',0)->plaintext;
	$date = $html->find('.quote_current_yes', 0)->find('.quote__date',0)->plaintext;
	$course = array( 'dollar' => $value, 'date' => $date, 'check' => current_time('mysql',1) );
	update_option( 'i_price_course_dollar', $course, 'no' );
}

// Выводит данные курса
function the_course_dollar( $data = null ){
	echo get_course_dollar( $data );
}

// Возвращает данные курса
function get_course_dollar( $data = null ){
	$course = get_option('i_price_course_dollar');
	if ( !$data || $data == 'dollar') return $course['dollar'];
	if ( $data == 'date') return $course['date'];
	if ( $data == 'check') return $course['check'];
}

#5 Обновление еще не выполненной крон задачи

Допустим у нас в плагине есть настройка интервала какой-то крон задачи. И нам нужно, обновлять интервал задачи в зависимости от указанной настройки.

Первое что нужно сделать это удалить текущую задачу и добавить новую. Также нужно учесть изменение настройки при изменении интервала для крон задачи.

Этот пример показывает как сделать такую операцию с плагином ACF. При обновлении опции которого нужно обновить крон задачу.

// функция выполнения крон задачи 'rs_cron_event'
add_action('rs_cron_event', 'rs_cron_rebuild_meta_products');
function rs_cron_rebuild_meta_products() {
	// выполняем задачу крон
	$headers = 'From: My Name <myname@mydomain.com>' . "\r\n";
	wp_mail('test@test.com', 'Тема', 'Содержание', $headers );
}

// добавим наш новый интервал для крона
add_filter( 'cron_schedules', 'rs_cron_interval');
function rs_cron_interval( $schedules, $value = '' ){
	// чтобы можно было указать значение жестко
	if( ! $value )
		$value = intval( get_option('options_rs_time_period') ?: 12 );

	$schedules['rs_time_period'] = array(
		'interval' => $value * HOUR_IN_SECONDS ,
		'display' => 'Задаётся в настройках плагина RS'
	);    

	return $schedules;
}

// Функция обновления поля
add_filter('acf/update_value/name=rs_time_period', 'my_acf_update_value', 10, 3);
function my_acf_update_value( $new_period, $post_id, $field  ) {

	$old_period = get_option('options_rs_time_period');

	// опция изменилась, перезапишем крон задачу с новой настройкой!
	if( $new_period != $old_period ){
		// удалим имеющуюся крон задачу
		$timestamp = wp_next_scheduled('rs_cron_event');
		wp_unschedule_event( $timestamp, 'rs_cron_event');

		// изменим интервал чтобы задача добавилось правильно...
		add_filter( 'cron_schedules', function( $schedules ) use ( $new_period ){
			return rs_cron_interval( $schedules, $new_period ); // костылёк жестко укажем интервал
		} );

		// добавим крон задача снова
		wp_reschedule_event( time(), 'rs_time_period', 'rs_cron_event' );
	}

	return $new_period;
}

#6 Класс для удобного добавления крон событий

Смотрите в статье Kama_Cron.

Список изменений

С версии 2.1.0 Введена.
С версии 5.1.0 Return value modified to boolean indicating success or failure, 'pre_schedule_event' filter added to short-circuit the function.

Код wp_schedule_event() WP 5.5.1

wp-includes/cron.php
<?php
function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
	// Make sure timestamp is a positive integer.
	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
		return false;
	}

	$schedules = wp_get_schedules();

	if ( ! isset( $schedules[ $recurrence ] ) ) {
		return false;
	}

	$event = (object) array(
		'hook'      => $hook,
		'timestamp' => $timestamp,
		'schedule'  => $recurrence,
		'args'      => $args,
		'interval'  => $schedules[ $recurrence ]['interval'],
	);

	/** This filter is documented in wp-includes/cron.php */
	$pre = apply_filters( 'pre_schedule_event', null, $event );
	if ( null !== $pre ) {
		return $pre;
	}

	/** This filter is documented in wp-includes/cron.php */
	$event = apply_filters( 'schedule_event', $event );

	// A plugin disallowed this event.
	if ( ! $event ) {
		return false;
	}

	$key = md5( serialize( $event->args ) );

	$crons = _get_cron_array();
	$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
		'schedule' => $event->schedule,
		'args'     => $event->args,
		'interval' => $event->interval,
	);
	uksort( $crons, 'strnatcasecmp' );
	return _set_cron_array( $crons );
}

Cвязанные функции

Из метки: cron (расписание schedule)

28 комментов
Полезные 4 Вопросы 1 Все