WooCommerce: автоматическое удаление заказов по статусу и времени через код

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

При активном интернет-магазине на WooCommerce количество заказов быстро растет. Особенно если не удалять отменённые, неоплаченные или старые заказы, база данных разрастается, что ухудшает производительность и увеличивает время резервного копирования. Многие пользователи сталкиваются с замедлением админки и увеличением нагрузки на сервер.

Диагностировать проблему можно через:

  • Панель состояния WooCommerce (Статус > База данных) — смотрите количество заказов и размер таблиц.
  • Плагины для мониторинга базы, например Query Monitor — выявляют медленные запросы.
  • Прямой запрос к базе для подсчёта количества заказов по статусам:
SELECT post_status, COUNT(*) FROM wp_posts WHERE post_type = 'shop_order' GROUP BY post_status;

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

1. Подключение WP-Cron для регулярной проверки

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

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

2. Функция удаления заказов по статусу и возрасту

Удаляем заказы со статусом cancelled и failed, которым больше 30 дней.

function wc_delete_old_orders() {
    global $wpdb;
    $statuses = [ 'wc-cancelled', 'wc-failed' ];
    $days_old = 30;
    $date_threshold = date( 'Y-m-d H:i:s', strtotime( "-{$days_old} days" ) );

    foreach ( $statuses as $status ) {
        $order_ids = $wpdb->get_col( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_order' AND post_status = %s AND post_date < %s",
            $status,
            $date_threshold
        ) );

        if ( ! empty( $order_ids ) ) {
            foreach ( $order_ids as $order_id ) {
                wp_delete_post( $order_id, true ); // true — удаление без перемещения в корзину
            }
        }
    }
}
add_action( 'wc_order_cleanup_hook', 'wc_delete_old_orders' );

3. Настройка времени удаления и расширение на другие статусы

Для удаления неоплаченных заказов pending через 7 дней измените $statuses и $days_old соответственно:

$statuses = [ 'wc-pending' ];
$days_old = 7;

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

  • Выполните ручной запуск крон-задачи, чтобы проверить сразу:
do_action( 'wc_order_cleanup_hook' );
  • Проверьте наличие заказов старше указанного срока с помощью SQL-запроса.
  • В админке WooCommerce количество заказов со статусом cancelled и failed должно уменьшиться.
  • Проверьте логи ошибок для исключения сбоев при удалении.

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

  • Заказы не удаляются: проверьте, что хук wc_order_cleanup_hook правильно регистрируется и cron срабатывает. Используйте плагин WP Crontrol для диагностики.
  • Удаляются не те заказы: внимательно проверьте статус заказа в базе, в WooCommerce статусы начинаются с wc-. Например, wc-cancelled, а не просто cancelled.
  • Производительность страдает при большом числе заказов: разбивайте удаление на партии по 50-100 заказов, добавляя ограничение в SQL, чтобы не перегружать сервер.

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

  • Используйте wp_delete_post( $order_id, true ) для полного удаления без возможности восстановления, чтобы не накапливались записи в корзине.
  • Проверяйте права пользователя, если добавляете интерфейс для запуска удаления вручную.
  • Добавьте логирование удалённых заказов для аудита и отладки:
function wc_delete_old_orders() {
    global $wpdb;
    $statuses = [ 'wc-cancelled', 'wc-failed' ];
    $days_old = 30;
    $date_threshold = date( 'Y-m-d H:i:s', strtotime( "-{$days_old} days" ) );

    foreach ( $statuses as $status ) {
        $order_ids = $wpdb->get_col( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_order' AND post_status = %s AND post_date < %s LIMIT 100",
            $status,
            $date_threshold
        ) );

        if ( ! empty( $order_ids ) ) {
            foreach ( $order_ids as $order_id ) {
                if ( wp_delete_post( $order_id, true ) ) {
                    error_log( "Удалён заказ #{$order_id} со статусом {$status}" );
                }
            }
        }
    }
}
add_action( 'wc_order_cleanup_hook', 'wc_delete_old_orders' );

Сравнение вариантов реализации

МетодПлюсыМинусыРекомендуется для
Плагин автоматической очистки заказовПростой в настройке, интерфейсДополнительные нагрузки, зависит от разработчикаПользователи без навыков кодирования
Кастомный код с WP-CronТочный контроль, отсутствие лишних плагиновТребует навыков программированияРазработчики и опытные администраторы
Ручное удаление через SQLБыстро и напрямуюРиск повреждения базы, отсутствие логированияЭкстренные случаи и опытные администраторы
WooCommerce: как удалить товар и все его данные через код без плагинов
08.05.2026
Как создать адаптивные блоки в WordPress с помощью Gutenberg
22.01.2026
Как создать автоматические оценки в отзывах WordPress
10.04.2026
Как автоматически удалять старые чёрные спам-комментарии в WordPress
04.04.2026
WooCommerce: как удалить товар со всеми связями через код без плагинов
16.06.2026