Вопрос или проблема
Я пытаюсь создать запланированную cron-задачу, которая запускается каждый час. Это мой первый опыт работы с wp-cron.
В функции cron я хочу обновить значения мета полей постов, если соблюдены некоторые условия.
Я также протестировал код функции cron вне cron, чтобы увидеть/напечатать результаты. Результаты выглядели нормально, но когда запускается cron-задача, ни один пост не обновляется.
Я использую WP Crontrol, чтобы видеть все доступные cron-задачи.
Сначала я запланировал событие (это, кажется, работает):
function prfx_hourly_status_update_cron_job() {
if ( ! wp_next_scheduled( 'prfx_run_hourly_status_update_cron_job' ) ) {
wp_schedule_event( current_time( 'timestamp' ), 'hourly', 'prfx_run_hourly_status_update_cron_job' );
}
}
add_action( 'wp', 'prfx_hourly_status_update_cron_job' );
После создания этого события я пытаюсь запустить эту функцию.
Я получаю все посты, у которых есть мета поле, где значение не пусто.
Это поле — дата. (Y-m-d)
Для каждого поста/продукта я получаю два мета значения.
Дедлайн-дата и более ранняя дата-срочный-дедлайн.
Затем я сравниваю сегодняшнюю дату с этими сохраненными датами и хочу обновить другое мета значение на основе этого.
function prfx_run_hourly_status_update_cron_job() {
// создать мета запрос, чтобы получить все посты, у которых есть дата дедлайна (поле не пустое)
$args = array(
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_prfx_custom_product_deadline',
'value' => '',
'compare' => '!='
),
),
'post_type' => 'product',
'no_found_rows' => true, //значительно ускоряет запрос и может быть установлен на 'true', если не используется пагинация
'fields' => 'ids', //снова для производительности
);
$posts_array = get_posts( $args );
// начать, если есть посты
if ($posts_array) {
// получить сегодняшнюю дату в формате Y-m-d
$today = date('Y-m-d');
//теперь проверить условия и обновить код
foreach( $posts_array as $post_id ){
$saved_deadline = get_post_meta( $post_id, '_prfx_custom_product_deadline', true ); // получить дедлайн-дата
$soon_deadline = get_post_meta( $post_id, '_prfx_custom_product_deadline_soon', true );// получить срочный-дедлайн-дата
if ($today > $saved_deadline) { // если сегодня после дедлайна
update_post_meta( $post_id, '_prfx_custom_product_status', 'deadline-met' );
} elseif ($today < $saved_deadline && $today > $soon_deadline) { // если сегодня перед дедлайном, но после срочного дедлайна
update_post_meta( $post_id, '_prfx_custom_product_status', 'deadline-soon' );
}
}
}
}
Как сказано выше, я попытался провести сухой запуск этой функции, вместо update_post_meta я просто выводил данные. Это, кажется, работает. Я также использую аналогичную функцию для вывода некоторых строк на фронтенде, так что сравнение дат тоже работает.
Обновление: Итак, мне не удалось заставить это работать с cron-задачами. Я только что протестировал следующий код в плагине, как только я активирую плагин, код запускается.
Запрос работает нормально, я распечатал/проверил результаты, и это работает как простой код плагина.
Но тот же код не работает в cron-задаче. Когда я смотрю на вывод cron с помощью WP Crontrol, я вижу ежечасное событие “prfx_run_hourly_status_update_cron_job”, но без какого-либо назначенного действия. Однако, например, “woocommerce_geoip_updater” также не имеет назначенного действия.
Может быть, у кого-то есть идея почему?
Вот протестированный код:
add_action('init','prfx_resave_posts');
function prfx_resave_posts(){
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_prfx_custom_product_deadline_soon',
'value' => '',
'compare' => '!='
),
),
'no_found_rows' => true, //значительно ускоряет запрос и может быть установлен на 'true', если не используется пагинация
'fields' => 'ids', //снова для производительности
);
$posts_array = get_posts( $args );
if ($posts_array) { //вывод: Array ( [0] => 120399 [1] => 120431 [2] => 120469 [3] => 120401 [4] => 120433 )
// получить сегодняшнюю дату в формате Y-m-d
$today = date('Y-m-d');
foreach ($posts_array as $my_post) {
#print_r($my_post);
//пример вывода: 120399
$saved_soon_deadline = get_post_meta( $my_post, '_prfx_custom_product_deadline_soon', true );
#print_r($saved_soon_deadline);
//вывод: 2018-11-30
if ($today > $saved_soon_deadline) {
update_post_meta( $my_post, '_prfx_custom_product_status', 'my-new-val-here' );
}
}
}
}
Что вы делаете, так это перебираете массив объектов постов.
Функция get_posts()
возвращает объекты, а не ID.
Поэтому вам нужно либо использовать
$post_id->ID
либо
setup_postdata( $post_id )
и затем использовать get_the_ID()
.
Возможно, стоит переименовать $post_id
в $post_object
, чтобы избежать путаницы.
Я точно не знаю, что произошло здесь, но нашел решение.
Код, который я опубликовал в первоначальном вопросе, находился внутри плагина с несколькими другими функциями и кодом.
Только что я создал отдельный плагин только для этого ежечасного cron, который я хотел бы использовать.
При активации плагина я добавляю новую cron-задачу, а при деактивации задача удаляется.
Но в любом случае, код для обновления мета поста остается таким же, как я и опубликовал. Так что я не знаю, почему это работает в отдельном файле плагина. Может быть, что-то было не так при настройке событий?
register_activation_hook( __FILE__, 'prfx_add_cronjob_on_activation' );
function prfx_add_cronjob_on_activation() {
wp_schedule_event( time(), 'hourly', 'prfx_update_status_job' );
}
register_deactivation_hook( __FILE__, 'prfx_delete_cronjob_on_deactivation' );
function prfx_delete_cronjob_on_deactivation() {
wp_clear_scheduled_hook( 'prfx_update_status_job' );
}
add_action( 'prfx_update_status_job', 'prfx_update_status_code' );
function prfx_update_status_code(){
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_prfx_custom_product_deadline',
'value' => '',
'compare' => '!='
),
),
'no_found_rows' => true, //значительно ускоряет запрос и может быть установлен на 'true', если не используется пагинация
'fields' => 'ids', //снова для производительности
);
$posts_array = get_posts( $args );
if ($posts_array) {
// получить сегодняшнюю дату в формате Y-m-d
$today = date('Y-m-d');
foreach ($posts_array as $single) {
$saved_deadline = get_post_meta( $single, '_prfx_custom_product_deadline', true );
$soon_deadline = get_post_meta( $single, '_prfx_custom_product_deadline_soon', true );
if ($today > $saved_deadline) {
update_post_meta( $single, '_prfx_custom_product_status', 'deadline-met' );
} else {
if ($soon_deadline && $today > $soon_deadline) {
update_post_meta( $single, '_prfx_custom_product_status', 'deadline-soon' );
}
}
}
}
}
Ответ или решение
WP-Cron — это механизм, встроенный в WordPress, который позволяет планировать выполнение различных задач в определенное время. Это может быть полезно для автоматического обновления мета-данных постов, как, например, в вашем случае.
Решение и его реализация
Чтобы реализовать обновление мета-данных с использованием WP-Cron, важно правильно организовать процесс планирования и выполнения. Давайте разберемся, как это сделать:
1. Регистрация и удаление cron-задач
Создайте отдельный плагин для управления cron-задачами. Это помогает минимизировать шанс на конфликты и проблемы с существующим кодом.
register_activation_hook( __FILE__, 'prfx_add_cronjob_on_activation' );
function prfx_add_cronjob_on_activation() {
if (!wp_next_scheduled('prfx_update_status_job')) {
wp_schedule_event(time(), 'hourly', 'prfx_update_status_job');
}
}
register_deactivation_hook( __FILE__, 'prfx_delete_cronjob_on_deactivation' );
function prfx_delete_cronjob_on_deactivation() {
wp_clear_scheduled_hook('prfx_update_status_job');
}
Обратите внимание: wp_next_scheduled
проверяет, запланировано ли событие, чтобы не создавать его дубликаты.
2. Определение функции для обновления статуса
Создайте функцию, которая будет вызываться задачей cron, и привяжите ее к действию ‘prfx_update_status_job’.
add_action('prfx_update_status_job', 'prfx_update_status_code');
function prfx_update_status_code(){
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_prfx_custom_product_deadline',
'value' => '',
'compare' => '!='
),
),
'no_found_rows' => true,
'fields' => 'ids',
);
$posts_array = get_posts($args);
if ($posts_array) {
$today = date('Y-m-d');
foreach ($posts_array as $post_id) {
$saved_deadline = get_post_meta($post_id, '_prfx_custom_product_deadline', true);
$soon_deadline = get_post_meta($post_id, '_prfx_custom_product_deadline_soon', true);
if ($today > $saved_deadline) {
update_post_meta($post_id, '_prfx_custom_product_status', 'deadline-met');
} elseif ($soon_deadline && $today > $soon_deadline) {
update_post_meta($post_id, '_prfx_custom_product_status', 'deadline-soon');
}
}
}
}
Оптимизация и отладка
- Проверьте вывод get_posts: Используйте параметр
fields => 'ids'
для ускорения выполнения запроса, если вам нужны только идентификаторы. - Отладка cron-задач: Используйте плагин WP Crontrol для мониторинга и диагностики состояния cron-задач. Если задачи не запускаются, проверьте планировщик WP-Cron.
Заключение
Теперь ваши cron-задачи будут запланированы и выполнены корректно. Очень важно проверять, активируются ли задачи cron, и следить за состоянием мета-данных, которые обновляются. Это поможет вам поддерживать актуальность данных на вашем сайте WordPress. Используйте предложенную структуру и обеспечьте четкую организацию кода, чтобы минимизировать риск ошибок.