Диагностика проблемы: зачем удалять отменённые и возвращённые заказы
В крупных интернет-магазинах на WooCommerce количество отменённых и возвращённых заказов со временем растёт, засоряя базу данных и замедляя работу сайта. Это особенно заметно при использовании расширенной аналитики и отчётов, где старые заказы создают лишнюю нагрузку. Ручное удаление заказов неудобно и рискованно. Поэтому важна автоматизация этого процесса.
Пошаговое решение: автоматическое удаление заказов по статусу
1. Добавление кода в functions.php вашей темы или в кастомный плагин
Для удаления заказов со статусом cancelled (отменён) и refunded (возвращён) используем хук wp_scheduled_delete — он вызывается при очистке корзины для мусора и устаревших данных. Добавим функцию, которая будет искать заказы и удалять их безвозвратно.
add_action('wp_scheduled_delete', 'wc_auto_delete_cancelled_refunded_orders');
function wc_auto_delete_cancelled_refunded_orders() {
if (!class_exists('WC_Order_Query')) {
return;
}
$statuses_to_delete = array('cancelled', 'refunded');
foreach ($statuses_to_delete as $status) {
$query = new WC_Order_Query(array(
'limit' => -1, // без лимита
'status' => $status,
'return' => 'ids',
'date_modified' => '<' . (time() - MONTH_IN_SECONDS * 3), // старше 3 месяцев
));
$order_ids = $query->get_orders();
foreach ($order_ids as $order_id) {
wp_delete_post($order_id, true); // true — безвозвратно
}
}
}2. Настройка интервала выполнения задачи WP-Cron
По умолчанию wp_scheduled_delete запускается еженощно. Если хотите более частое удаление, добавьте кастомный интервал:
add_filter('cron_schedules', 'custom_cron_intervals');
function custom_cron_intervals($schedules) {
$schedules['every_six_hours'] = array(
'interval' => 21600, // 6 часов в секундах
'display' => __('Каждые 6 часов')
);
return $schedules;
}
if (!wp_next_scheduled('wp_scheduled_delete')) {
wp_schedule_event(time(), 'every_six_hours', 'wp_scheduled_delete');
}Проверка результата после внедрения
- Создайте тестовый заказ со статусом
cancelledилиrefunded, установите дату изменения более 3 месяцев назад (через phpMyAdmin или плагин для управления базой). - Принудительно запустите задачу WP-Cron, например, с помощью плагина WP Crontrol или вызвав
do_action('wp_scheduled_delete')в консоли WP-CLI. - Проверьте, что заказ удалён из базы и больше не отображается в админке WooCommerce.
- Убедитесь, что остальные заказы не пострадали.
Частые ошибки и как их исправить
- Заказы не удаляются: Проверьте, активен ли WP-Cron и запускается ли задача
wp_scheduled_delete. Можно проверить с помощью плагина WP Crontrol. - Удаляются нужные заказы: Убедитесь, что фильтр
'date_modified'настроен корректно и не затрагивает свежие заказы. - Проблемы с производительностью при большом количестве заказов: Разбейте удаление на партии с лимитом, например, по 100 заказов за раз.
- Ошибки при удалении из-за зависимостей плагинов: Проверьте совместимость и отключите сторонние плагины, влияющие на типы заказов.
Практические советы по безопасности и производительности
- Создайте резервную копию базы данных перед внедрением автоматического удаления.
- Используйте транзакции или WP-CLI для пакетного удаления, если заказов много, чтобы избежать таймаутов.
- Не удаляйте заказы, которые могут понадобиться для отчетности или возвратов налогов — согласуйте с бухгалтерией.
- Мониторьте логи ошибок сервера и WP, чтобы вовремя заметить сбои.
Таблица сравнения способов удаления заказов
| Метод | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| Ручное удаление через админку | Простота, контроль | Трудозатратно, риск ошибок | Подходит для малых магазинов |
| Автоудаление через WP-Cron + код | Автоматизация, экономия времени | Нужна настройка и тесты | Оптимально для средних и больших магазинов |
| Плагины очистки базы | Удобство, доп. функции | Может конфликтовать, нагрузка | Использовать с осторожностью, тестировать |
Дополнительный пример: удаление старых заказов партиями
function wc_delete_orders_in_batches($status, $batch_size = 100) {
$query = new WC_Order_Query(array(
'limit' => $batch_size,
'status' => $status,
'return' => 'ids',
'date_modified' => '<' . (time() - MONTH_IN_SECONDS * 3),
));
$order_ids = $query->get_orders();
foreach ($order_ids as $order_id) {
wp_delete_post($order_id, true);
}
return count($order_ids);
}
add_action('wp_scheduled_delete', function() {
$statuses = array('cancelled', 'refunded');
foreach ($statuses as $status) {
while (wc_delete_orders_in_batches($status) > 0) {
// продолжаем удалять пока есть заказы
}
}
});