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

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

В интернет-магазинах на WooCommerce часто накапливаются заказы со статусом, который можно назвать «заблокированными» или «зависшими» (например, «on-hold», «pending payment» или кастомные статусы), которые не обрабатываются дальше и не удаляются автоматически. Это приводит к раздуванию базы данных, замедлению работы админки и усложнению отчетности.

Чтобы понять, есть ли такая проблема, выполните SQL-запрос к базе данных (через phpMyAdmin или WP CLI):

SELECT COUNT(*) as count, post_status FROM wp_posts WHERE post_type = 'shop_order' GROUP BY post_status;

Если вы видите большое количество заказов с неподвижным статусом (например, «wc-on-hold» или «wc-pending»), которые не менялись длительное время, это повод автоматизировать их удаление.

Как автоматически удалять заблокированные заказы с помощью кода

Настройка WP-Cron задачи для регулярной очистки

Для автоматического удаления старых заказов определенного статуса добавим функцию и запустим её по расписанию.

Пример кода для удаления заказов старше 7 дней со статусом «on-hold»

function wpaction_delete_old_on_hold_orders() {
    global $wpdb;
    $days = 7; // количество дней, старше которых заказы удаляются
    $cutoff_date = date('Y-m-d H:i:s', strtotime("-{$days} days"));

    // Получаем ID заказов со статусом on-hold и датой создания раньше cutoff_date
    $order_ids = $wpdb->get_col($wpdb->prepare(
        "SELECT ID FROM {$wpdb->posts} 
         WHERE post_type = 'shop_order' 
         AND post_status = 'wc-on-hold' 
         AND post_date < %s",
         $cutoff_date
    ));

    if (!empty($order_ids)) {
        foreach ($order_ids as $order_id) {
            wp_delete_post($order_id, true); // true - без отправки в корзину
        }
    }
}

// Регистрируем расписание, если не существует
add_filter('cron_schedules', function($schedules) {
    if (!isset($schedules['daily_custom'])) {
        $schedules['daily_custom'] = [
            'interval' => 86400, // 24 часа
            'display'  => 'Once Daily Custom'
        ];
    }
    return $schedules;
});

// Планируем задачу при активации темы или плагина
if (!wp_next_scheduled('wpaction_delete_old_on_hold_orders_hook')) {
    wp_schedule_event(time(), 'daily_custom', 'wpaction_delete_old_on_hold_orders_hook');
}

// Хук для запуска функции
add_action('wpaction_delete_old_on_hold_orders_hook', 'wpaction_delete_old_on_hold_orders');

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

1. Запустите функцию вручную для теста в админке (через подключение к functions.php или через плагин для сниппетов):

wpaction_delete_old_on_hold_orders();

2. Проверьте, что заказы со статусом wc-on-hold старше 7 дней удалились (через админку WooCommerce или SQL-запрос выше).

3. Для проверки работы WP-Cron можно использовать плагин WP Crontrol, чтобы увидеть запланированные события и запускать их вручную.

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

  • Заказы не удаляются: Проверьте, правильно ли указан статус заказа (например, WooCommerce использует префикс wc-, то есть wc-on-hold вместо просто on-hold).
  • Функция не запускается по расписанию: Убедитесь, что WP-Cron работает (на некоторых серверах WP-Cron отключен и нужно настроить системный cron).
  • Удаляются не те заказы: Проверьте, что условие по дате и статусу корректно. Можно временно вывести IDs для отладки.
  • Удаление занимает слишком много времени: Если заказов очень много, разбейте удаление на пакеты, чтобы избежать таймаутов и перегрузки сервера.

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

  • Для безопасности используйте wp_delete_post($order_id, true) с параметром true, чтобы удалять заказ полностью, а не отправлять в корзину.
  • Резервное копирование базы перед внедрением автоматического удаления обязательно.
  • Добавьте логирование удаленных заказов, чтобы отслеживать историю очистки:
function wpaction_delete_old_on_hold_orders() {
    global $wpdb;
    $days = 7;
    $cutoff_date = date('Y-m-d H:i:s', strtotime("-{$days} days"));
    $order_ids = $wpdb->get_col($wpdb->prepare(
        "SELECT ID FROM {$wpdb->posts} 
         WHERE post_type = 'shop_order' 
         AND post_status = 'wc-on-hold' 
         AND post_date < %s",
         $cutoff_date
    ));

    if (!empty($order_ids)) {
        foreach ($order_ids as $order_id) {
            $deleted = wp_delete_post($order_id, true);
            if ($deleted) {
                error_log("WooCommerce: удален заказ ID {$order_id} старше {$days} дней");
            }
        }
    }
}
  • При большом количестве заказов настроить пакетную обработку, например по 50 заказов за вызов, с последующим повтором.
  • Для удобства можно расширить функционал и добавить страницу настроек, где администратор сможет менять параметры (статус, срок удаления).

Сравнение вариантов автоматического удаления заказов

МетодПлюсыМинусыПример
Через код с WP-CronПолный контроль, нет зависимостей, бесплатноТребуется навыки PHP, риск ошибок при неправильном кодеКод в functions.php из статьи
Плагины автоматизации (например, WP Bulk Delete)Простой интерфейс, много настроекДополнительная нагрузка, не всегда гибкоWP Bulk Delete
Ручное удаление через админкуПросто и понятноТрудозатратно, не автоматичноРучной выбор и удаление заказов
Как добавить настройки для плагинов в WordPress с примерами кода
22.02.2026
Как избежать конфликтов плагинов в WordPress
13.12.2025
Как отключить индексацию страниц автора и архивов в WordPress без потери нужного трафика
19.08.2026
WooCommerce: как автоматически отключать отложенные оплаты при превышении срока
29.05.2026
Как отключить автоматические обновления в WordPress с помощью кода
04.03.2026