WooCommerce: Автоматическое удаление неактивных заказов по расписанию с WP-Cron

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

В магазинах на WooCommerce со временем накапливаются заказы в статусах, которые не были завершены или оплачены, например, «в ожидании оплаты» или «отменён». Это приводит к засорению базы данных и замедлению работы сайта. Ручное удаление неудобно и ошибочно. Задача — настроить автоматическое удаление таких заказов по расписанию с помощью стандартного WP-Cron, без сторонних плагинов.

Диагностика проблемы

Для начала нужно выявить, какие статусы заказов считаются неактивными и требуют удаления. Обычно это:

  • pending — ожидает оплаты;
  • failed — оплата не прошла;
  • cancelled — отменён пользователем или админом;
  • on-hold — ожидает подтверждения.

Проверить, сколько таких заказов в базе, можно SQL-запросом:

SELECT COUNT(*) FROM wp_posts WHERE post_type = 'shop_order' AND post_status IN ('wc-pending', 'wc-failed', 'wc-cancelled', 'wc-on-hold');

Также важно понять, за какой период заказы считаются старыми и подлежат удалению. Обычно это 7 или 14 дней с момента создания.

Пошаговое решение: настройка автоматического удаления заказов

1. Создаём функцию удаления заказов

Добавьте следующий код в файл functions.php вашей дочерней темы или в кастомный плагин:

function wpassist_delete_old_inactive_orders() {
    $days = 14; // количество дней для хранения неактивных заказов
    $statuses = array('wc-pending', 'wc-failed', 'wc-cancelled', 'wc-on-hold');

    $date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));

    $args = array(
        'post_type'      => 'shop_order',
        'post_status'    => $statuses,
        'date_query'     => array(
            array(
                'before' => $date_threshold,
                'column' => 'post_date',
            ),
        ),
        'posts_per_page' => -1,
        'fields'         => 'ids',
        'no_found_rows'  => true,
    );

    $orders = get_posts($args);

    if (!empty($orders)) {
        foreach ($orders as $order_id) {
            wp_delete_post($order_id, true); // Полное удаление без корзины
        }
    }
}

2. Регистрируем WP-Cron событие

Чтобы задача запускалась ежедневно, добавьте в functions.php:

function wpassist_schedule_order_deletion() {
    if (!wp_next_scheduled('wpassist_daily_delete_orders')) {
        wp_schedule_event(time(), 'daily', 'wpassist_daily_delete_orders');
    }
}
add_action('wp', 'wpassist_schedule_order_deletion');

add_action('wpassist_daily_delete_orders', 'wpassist_delete_old_inactive_orders');

3. Очистка при деактивации плагина или темы

Чтобы избежать множества запланированных задач, рекомендуется удалить расписание при деактивации:

function wpassist_clear_scheduled_order_deletion() {
    $timestamp = wp_next_scheduled('wpassist_daily_delete_orders');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'wpassist_daily_delete_orders');
    }
}
register_deactivation_hook(__FILE__, 'wpassist_clear_scheduled_order_deletion');

Проверка результата после внедрения

  • В базе данных wp_posts количество заказов с указанными статусами и датой создания старше 14 дней должно уменьшиться.
  • Проверьте журнал ошибок PHP (если включён), чтобы убедиться, что функция запускается без ошибок.
  • Для теста можно временно уменьшить $days до 0 или 1, чтобы увидеть, что заказы удаляются сразу.
  • Запустите вручную функцию из админки или через WP CLI wp eval 'wpassist_delete_old_inactive_orders();' для проверки.

Частые ошибки и как их исправить

  • WP-Cron не срабатывает: Проверьте, что на сайте есть трафик, так как WP-Cron запускается по посещениям. Для автоматизации используйте системный cron, вызывающий wp-cron.php.
  • Заказы не удаляются: Убедитесь, что статусы заказов указаны с префиксом wc- и совпадают с текущими статусами WooCommerce.
  • Удаляются не те заказы: Проверьте условие даты и статусов — возможно, стоит использовать post_modified вместо post_date или добавить дополнительные проверки.
  • Ошибка прав доступа: Для удаления заказов функция должна запускаться с правами администратора или из контекста, где доступ к базе открыт.

Практические советы по безопасности и производительности

  • Безопасность: Удаление заказов — критичная операция. Рекомендуется делать резервное копирование базы перед внедрением.
  • Производительность: При большом количестве заказов разбивайте удаление на партии, чтобы избежать таймаутов:
function wpassist_delete_old_inactive_orders_batch() {
    $days = 14;
    $statuses = array('wc-pending', 'wc-failed', 'wc-cancelled', 'wc-on-hold');
    $batch_size = 50;

    $date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));

    $args = array(
        'post_type'      => 'shop_order',
        'post_status'    => $statuses,
        'date_query'     => array(
            array(
                'before' => $date_threshold,
                'column' => 'post_date',
            ),
        ),
        'posts_per_page' => $batch_size,
        'fields'         => 'ids',
        'no_found_rows'  => true,
    );

    $orders = get_posts($args);

    if (empty($orders)) {
        return;
    }

    foreach ($orders as $order_id) {
        wp_delete_post($order_id, true);
    }
}
  • Добавьте логирование действий, чтобы отслеживать удалённые заказы.
  • Проверяйте совместимость с плагинами резервного копирования и кэширования, которые могут блокировать удаление.

Сравнение решений: плагин vs кастомный код

КритерийПлагинКастомный код (WP-Cron)Компромисс
УправлениеУдобный интерфейсТребует редактирования кодаБольше контроля, но сложнее
Нагрузка на серверМожет добавлять нагрузкуОптимизирован под сайтКод можно адаптировать под нагрузку
ГибкостьОграничена функционалом плагинаМаксимальная, под любые задачиКод требует поддержки
БезопасностьЗависит от автора плагинаКонтроль за всеми операциямиТребует знаний разработки
Как создать простой shortcode в WordPress с применением
04.11.2025
Как добавить динамические табуляторы в WordPress без плагинов
10.04.2026
WooCommerce: автоматическое изменение стоимости товаров по расписанию без плагинов
10.07.2026
Как изменить имя автора в сообщениях WordPress
27.03.2026
Как создать и использовать кастомные статусы записей в WordPress
16.11.2025