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

Почему важно удалять неактивные заказы в WooCommerce

Неактивные заказы (в статусах, например, "ожидает оплаты" или "обработка", которые долго не меняются) занимают место в базе данных и могут замедлять работу сайта, усложнять отчёты и мешать управлению заказами. Автоматизация удаления таких заказов поможет поддерживать чистоту данных и повысит производительность.

Диагностика проблемы: как определить устаревшие заказы

Для начала нужно понять, какие заказы считать неактивными и как долго они находятся в таком состоянии. Обычно это заказы со статусом pending, on-hold или failed, которые не менялись более 30 дней.

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

SELECT COUNT(*) FROM wp_posts WHERE post_type = 'shop_order' AND post_status IN ('wc-pending', 'wc-on-hold', 'wc-failed') AND post_date < NOW() - INTERVAL 30 DAY;

Если число большое, то стоит настроить автоматическое удаление.

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

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

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

function wptool_delete_old_inactive_orders() {
    $days = 30; // период неактивности
    $statuses = array('wc-pending', 'wc-on-hold', 'wc-failed');

    $args = array(
        'post_type'      => 'shop_order',
        'post_status'    => $statuses,
        'date_query'     => array(
            array(
                'column' => 'post_date',
                'before' => "$days days ago",
            ),
        ),
        'posts_per_page' => 100, // за раз удаляем по 100 заказов
        'fields'         => 'ids',
        'no_found_rows'  => true,
    );

    $orders = get_posts($args);

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

2. Автоматизация с помощью WP-Cron

Чтобы запускать функцию регулярно, зарегистрируем событие WP-Cron. Для этого добавьте в functions.php:

// Регистрируем событие при активации темы или плагина
function wptool_schedule_order_cleanup() {
    if (!wp_next_scheduled('wptool_daily_order_cleanup')) {
        wp_schedule_event(time(), 'daily', 'wptool_daily_order_cleanup');
    }
}
add_action('wp', 'wptool_schedule_order_cleanup');

// Снимаем расписание при деактивации темы или плагина
function wptool_unschedule_order_cleanup() {
    $timestamp = wp_next_scheduled('wptool_daily_order_cleanup');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'wptool_daily_order_cleanup');
    }
}
// add_action('switch_theme', 'wptool_unschedule_order_cleanup'); // если в теме

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

Если используете плагин, создайте соответствующие хуки активации/деактивации для расписания.

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

Проверьте, что заказы удаляются корректно:

  • Запустите функцию вручную (например, вызвав wptool_delete_old_inactive_orders() через WP-CLI или временно добавив вызов в functions.php).
  • Проверьте, что заказы с нужными статусами и датами действительно удаляются.
  • Проверьте базу данных на уменьшение количества таких заказов.
  • Убедитесь, что на сайте и в админке нет ошибок.

Для отладки можно добавить логирование:

function wptool_delete_old_inactive_orders() {
    $days = 30;
    $statuses = array('wc-pending', 'wc-on-hold', 'wc-failed');

    $args = array(
        'post_type'      => 'shop_order',
        'post_status'    => $statuses,
        'date_query'     => array(
            array('column' => 'post_date', 'before' => "$days days ago"),
        ),
        'posts_per_page' => 100,
        'fields'         => 'ids',
        'no_found_rows'  => true,
    );

    $orders = get_posts($args);

    if (!empty($orders)) {
        foreach ($orders as $order_id) {
            if (wp_delete_post($order_id, true)) {
                error_log("Order $order_id deleted");
            } else {
                error_log("Failed to delete order $order_id");
            }
        }
    } else {
        error_log("No orders to delete");
    }
}

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

  • Заказы не удаляются: Проверьте, что функция вызывается (проверьте логи), и что у пользователя/сервера есть права на удаление.
  • Удаляются не те заказы: Проверьте правильность условий post_status и date_query. Можно временно вывести print_r($orders) для отладки.
  • WP-Cron не срабатывает: Убедитесь, что на сайте есть посещения (WP-Cron запускается при посещении), или настройте системный cron для wp-cron.php.
  • Потеря данных: Обязательно делайте резервные копии перед автоматическим удалением.

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

  • Удаление большого количества заказов за один раз может нагружать сервер. Разбейте удаление на небольшие партии (например, 100 штук за раз).
  • Всегда используйте wp_delete_post($id, true) для полного удаления вместе с метаданными.
  • Реализуйте систему резервных копий перед автоматическими удалениями.
  • Если нужно, добавьте возможность отключать автоматическую очистку через настройку или константу.

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

МетодПлюсыМинусы
Тестовый плагин для удаления заказовПростота, готовое решениеМожет содержать лишний функционал, нагрузки не контролируются
Ручной SQL-запросБыстро и без накладных затратРиск потери связных данных, требует знаний SQL
Собственный WP-Cron с PHP-кодом (наш вариант)Контроль, гибкость, безопасностьТребует базовых навыков PHP и понимания WP-Cron
Как установить автоматическую защиту от Brute Force в WordPress
12.04.2026
Как добавить автоматически работающий кэш в WordPress с примерами кода
01.01.2026
Автоматический отчет по активности пользователей в WordPress: как сделать и настроить
17.02.2026
Автоматическое удаление старого контента в WordPress по типу постов и дате
14.03.2026
WooCommerce: автоматическое изменение цен при изменении атрибутов товара
13.06.2026