WP Cron Не Выполняется По Истечении Времени
Цель
Я хочу использовать wp_schedule_single_event( )
для выполнения одного события, которое отправляет мне электронное письмо через 8 минут после того, как пользователь отправит форму.
Проблема
Следующий код находится в моем functions.php
:
function nkapi_send_to_system( $args ) {
wp_mail( 'xxx', 'xxx', $args );
}
add_action( 'nkapi_send', 'nkapi_send_to_system' );
function schedule_event( $id ) {
wp_schedule_single_event( current_time( 'timestamp' ) + 480, 'nkapi_send', array( $id ) );
}
И следующий код используется для вызова schedule-event
:
schedule_event( $_SESSION['insert_id'] ); // the $_SESSION var contains an INT
После ожидания более 8 минут в моем почтовом ящике не было электронного письма.
Что я пробовал
С помощью плагина Управление ядром можно увидеть, что запланированы задания cron.
После нескольких изменений мне удалось сделать их совершенно правильными, и лучше, когда я нажимаю "Запустить сейчас", я действительно получаю электронное письмо в свой почтовый ящик.
Но почему хроны не выполняются, когда я захожу на свой сайт через 8 минут. Что, возможно, не так с этим кодом? Я должен сказать, что это мой первый раз, когда я использую WP Cron.
Я пробовал больше
После комментария ванкодера id решил проверить, соответствует ли код работает, если я помещу следующий код непосредственно в functions.php
:
function schedule_event( $id ) {
wp_schedule_single_event( time(), 'nkapi_send', array( $id ) );
}
if ( isset( $_SESSION['insert_id'] ) ) {
if ( ! array_key_exists( 'insert_scheduled', $_SESSION ) || $_SESSION['insert_scheduled'] != $_SESSION['insert_id'] ) {
schedule_event( $_SESSION['insert_id'] );
$_SESSION['insert_scheduled'] = $_SESSION['insert_id'];
}
}
Недостатком этого кода является то, что пользователь должен перейти на другую страницу, прежде чем этот код будет выполнен. Но с другой стороны, это тоже не работает, так что это не будет моей первой проблемой...
6 answers
Во-первых, не могли бы вы подтвердить, что у вас не включены какие-либо плагины кэширования? Плагины кэширования могут мешать заданиям cron, потому что вашим посетителям предоставляется не живая страница, а кэшированная версия вашей страницы.
Если у вас включен плагин кэширования, вы можете выбрать одну из своих страниц, добавить исключение в настройки плагина кэширования для этой страницы, чтобы она никогда не кэшировалась.
Затем вам придется вручную создать задание cron (используя cpanel, если вы находитесь на общем хостинге среде или с терминала, если это VPS/выделенный сервер), который будет посещать эту страницу каждые несколько минут.
Надеюсь, это поможет!
Во-первых, определите свои пользовательские расписания заданий cron.
add_filter('cron_schedules', array($this, 'cron_schedules'));
public function cron_schedules($schedules){
$prefix = 'cron_';// Avoid conflict with other crons. Example Reference: cron_30_mins
$schedule_options = array(
'30_mins' => array(
'display' => '30 Minutes',
'interval' => '1800'
),
'1_hours' => array(
'display' => 'Hour',
'interval' => '3600'
),
'2_hours' => array(
'display' => '2 Hours',
'interval' => '7200'
)
);
/* Add each custom schedule into the cron job system. */
foreach($schedule_options as $schedule_key => $schedule){
$schedules[$prefix.$schedule_key] = array(
'interval' => $schedule['interval'],
'display' => __('Every '.$schedule['display'])
);
}
return $schedules;
}
Вам нужно решить, где и когда на самом деле запланировать мероприятие.
Вот только пример фрагмента кода, который вызывает метод пользовательского класса:
$schedule = $this->schedule_task(array(
'timestamp' => current_time('timestamp'), // Determine when to schedule the task.
'recurrence' => 'cron_30_mins',// Pick one of the schedules set earlier.
'hook' => 'custom_imap_import'// Set the name of your cron task.
));
Вот код, который фактически планирует событие:
private function schedule_task($task){
/* Must have task information. */
if(!$task){
return false;
}
/* Set list of required task keys. */
$required_keys = array(
'timestamp',
'recurrence',
'hook'
);
/* Verify the necessary task information exists. */
$missing_keys = array();
foreach($required_keys as $key){
if(!array_key_exists($key, $task)){
$missing_keys[] = $key;
}
}
/* Check for missing keys. */
if(!empty($missing_keys)){
return false;
}
/* Task must not already be scheduled. */
if(wp_next_scheduled($task['hook'])){
wp_clear_scheduled_hook($task['hook']);
}
/* Schedule the task to run. */
wp_schedule_event($task['timestamp'], $task['recurrence'], $task['hook']);
return true;
}
Теперь все, что вам нужно сделать, это позвонить по имени вашей пользовательской задачи cron. В этом примере имя задачи cron custom_imap_import
.
add_action('custom_imap_import', array($this, 'do_imap_import'));
public function do_imap_import(){
// .... Do stuff when cron is fired ....
}
Итак, в этом примере $this->do_imap_import();
вызывается каждые 30 минут (при условии, что у вас достаточно трафика на ваш сайт).
Примечания
Требуется посещение страницы, чтобы ваш cron срабатывал в нужное время.
Пример: Если вы запланировали задачу с интервалом в 30 минут, но никто не посещает ваш сайт в течение 4 часов, ваша работа cron не будет уволена, пока этот посетитель не зайдет на ваш сайт 4 часа спустя. Если вы действительно действительно нуждаетесь в своем задание запускается каждые 30 минут, затем рекомендуется настроить законное задание cron через вашего провайдера веб-хостинга, чтобы посещать ваш веб-сайт с требуемыми интервалами.
Задания cron WordPress не замедляют работу вашего сайта!
Возможно, вы думаете, что, если выполнение cron-скрипта займет много времени, посетителям придется ждать, пока скрипт будет выполнен. Нет! Как это может быть возможно? Если вы посмотрите на файл wp-cron.php
, вы найдете строка
ignore_user_abort(true);
Это конфигурация php.ini
, которая устанавливает, что если вы прекратите загрузку сайта/скрипта, скрипт не прекратит выполнение.
Если вы посмотрите на файл wp-includes/cron.php
, вы найдете такую строку:
wp_remote_post( $cron_url,
array('timeout' => 0.01,
'blocking' => false,
'sslverify' => apply_filters('https_local_ssl_verify', true)) );
Это означает, что WordPress будет ждать всего 0,01 секунды для запуска выполнения, затем оно будет прервано, но, как вы установили ignore_user_abort
в true
, скрипт будет выполняться. Эта функциональность является огромным преимуществом для выполнения больших скриптов в WordPress cron работа.
Функции, доступные для помощи:
WordPress Cron позволяет вам планировать задачи, но они будут выполняться только в том случае, если на сайт будет сделан запрос. Для каждого запроса, который получает WordPress, он проверяет, есть ли задания cron для обработки, и если да, то асинхронно отправляет запрос /wp-cron.php?doing_wp_cron
для обработки задания. Если запланированный запуск задания проходит без запроса, то процесс cron не будет запущен.
Поскольку вы можете просматривать и выполнять запланированные задания, вполне возможно, что запросов нет это запускает задание cron, особенно если вы используете плагин кэширования. Лучший вариант для переноса этого в более регулярное расписание - отключить проверку по умолчанию в WordPress и использовать crontab
.
Сначала, чтобы отключить проверку по умолчанию (которая может немного помочь с производительностью на стороне клиента), добавьте следующее в wp-config.php
:
// Disable default check for WordPress cron jobs on page loads
define( 'DISABLE_WP_CRON', true );
Затем вы создаете задачу для извлечения страницы wp-cron.php
раз в минуту для обработки любых заданий на серверной части, в командной строке введите crontab -e
, а затем добавьте строка, которая выглядит следующим образом:
*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null
Для любого, кто защищает свой (разрабатываемый) сайт от публичного доступа, аутентификация HTTP может быть причиной того, что WP Cron не работает.
На случай, если это может кому-то помочь, вот мой список того, что я сделал, прежде чем определить и понять требования WP Cron:
- Я заметил, что события были правильно запланированы и могли быть запущены с помощью WP-CLI.
- А также заметил, что доступ к /wp-cron.php?выполнение_wp_cron через браузер вызывало выполнение, как предлагается, например, в 13625.
- Официальная документация была прочитана.
- Я убедился, что параметр DISABLE_WP_CRON не установлен.
- И узнал, что ALTERNATE_WP_CRON был успешным, но неудовлетворительным обходным решением.
- Чтобы исключить ошибки регрессии, я попытался установить пару старых версий wordpress.
- Все плагины были отключены, а тема переключена на тему по умолчанию, чтобы изолировать проблему.
- Люди упоминали термин обратные связи , но, не имея связанных с этим ошибок или предупреждений, я счел это неуместным.
- Наконец, был найден вопрос с ответом, фактически объясняющим, как отлаживать cron.
- После присоединения Xdebug к wp_cron() я действительно мог видеть, что выполнение закончилось в wp_remote_post(), что явно не удалось.
Зная, что искать, я нашел эту отличную статью о причинах проблем WP Cron Джеффа Старра. В конце он ссылается на свой плагин wp-cron-http-auth.
Убедитесь, что параметр DISABLE_WP_CRON не задан в вашей конфигурации.
В противном случае попробуйте отключить все плагины (кроме core control - хотя я бы использовал wp-crontrol) и посмотрите, работают ли ваши основные задания. Если они это делают, вы где-то сталкиваетесь с помехами плагина.
Аналогично, попробуйте переключиться на стандартную тему для двадцатилетних.
Если ничего из этого не имеет значения, скорее всего, это проблема с хостингом.
Проверьте любой плагин, который скрывает Wordpress.
Как узнать, в этом ли проблема?
- Перейдите к http(ам)://yoursite.com/wp-cron.php Вы должны увидеть пустую страницу. Совершенно пустой.
- Кроме того, вы должны видеть в диспетчере заданий cron время в разделе "Следующее выполнение".:
(не только текст "В очереди", но и заданное время - для некоторых записей "В очереди" иногда нормально, но если это единственное, что вы видите - > ваш cron не работа.)
+1. Не верьте никаким плагинам, которые "проверяют, работает ли cron" - например, плагин проверки статуса WP Cron показал, что cron работает. Но на самом деле этого не произошло.
Вывод: Если это ошибка 404 - отключите а) не только плагины кэширования, как предлагают другие б), но и любые плагины, которые скрывают Wordpress.