Диагностика проблемы: зачем и когда нужно удалять заказы автоматически
В WooCommerce со временем накапливаются заказы со статусом «отменён», «в ожидании оплаты» и другие, которые больше не нужны для бизнеса. Они занимают место в базе данных и замедляют работу админки, особенно при большом количестве продаж. Автоматическое удаление таких заказов по сроку помогает поддерживать базу в чистоте без ручного труда.
Как определить заказы для удаления
Для начала нужно четко определить критерии удаления. Чаще всего это:
- Заказы со статусом
cancelledилиfailed - Заказы со статусом
pending, которые не были оплачены в течение определённого времени (например, 30 дней)
Для таких заказов можно настроить автоматическую очистку.
Пошаговое решение: создание WP-Cron задачи для удаления заказов
1. Добавляем функцию удаления заказов
function wpfind_delete_old_woocommerce_orders() {
$days_to_keep = 30; // количество дней для хранения заказов
$date = date('Y-m-d H:i:s', strtotime('-' . $days_to_keep . ' days'));
// Получаем заказы со статусами cancelled, failed, pending старше $days_to_keep
$args = array(
'limit' => -1,
'status' => array('cancelled', 'failed', 'pending'),
'date_created' => '<' . $date,
'return' => 'ids',
);
$orders = wc_get_orders($args);
foreach ($orders as $order_id) {
wp_delete_post($order_id, true); // безвозвратно удаляем заказ
}
}2. Регистрируем WP-Cron задачу
function wpfind_schedule_order_cleanup() {
if (!wp_next_scheduled('wpfind_daily_order_cleanup')) {
wp_schedule_event(time(), 'daily', 'wpfind_daily_order_cleanup');
}
}
add_action('wp', 'wpfind_schedule_order_cleanup');
add_action('wpfind_daily_order_cleanup', 'wpfind_delete_old_woocommerce_orders');3. Отключаем задачу при деактивации плагина или темы
function wpfind_clear_scheduled_order_cleanup() {
$timestamp = wp_next_scheduled('wpfind_daily_order_cleanup');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wpfind_daily_order_cleanup');
}
}
register_deactivation_hook(__FILE__, 'wpfind_clear_scheduled_order_cleanup');Проверка результата после внедрения
- В админке WooCommerce перейдите в «Заказы» и отфильтруйте по статусам
cancelled,failed,pending. Заказы старше 30 дней должны отсутствовать. - Для теста можно временно изменить значение
$days_to_keepна 0 или 1, запустить функцию вручную и проверить удаление. - Проверьте наличие запланированной задачи в разделе «Инструменты» > «Запланированные задачи» (с помощью плагина WP Crontrol) — должна быть ежедневная задача
wpfind_daily_order_cleanup.
Частые ошибки и как их исправить
- Удаление не происходит: возможно, WP-Cron отключен или не срабатывает на сайте. Для проверки запустите функцию вручную через admin-ajax или WP-CLI.
- Заказы не удаляются, а только видны как удалённые: используйте
wp_delete_post($order_id, true)с параметромtrueдля безвозвратного удаления. - Удаляются не те заказы: перепроверьте параметры запроса
wc_get_orders, особенно фильтр по дате и статусу. - Нагрузка на сервер: если заказов очень много, лучше удалять партиями, например, по 50 заказов за раз с помощью пагинации.
Практические советы по безопасности и производительности
- Перед запуском автоматического удаления сделайте резервную копию базы данных.
- Используйте WP-Cron вместо системного Cron, если нет доступа к серверу, но учтите, что WP-Cron срабатывает только при посещении сайта.
- Для больших магазинов рассмотрите удаление заказов партиями с сохранением прогресса в опциях.
- Контролируйте права доступа: убедитесь, что функция удаления не может запускаться случайно с фронтенда без проверки nonce или прав пользователя.
Пример улучшенной функции с удалением партиями
function wpfind_delete_old_orders_batch($batch_size = 50) {
$days_to_keep = 30;
$date = date('Y-m-d H:i:s', strtotime('-' . $days_to_keep . ' days'));
$args = array(
'limit' => $batch_size,
'status' => array('cancelled', 'failed', 'pending'),
'date_created' => '<' . $date,
'return' => 'ids',
);
$orders = wc_get_orders($args);
if (empty($orders)) {
return false; // Очистка завершена
}
foreach ($orders as $order_id) {
wp_delete_post($order_id, true);
}
return true; // Есть ещё заказы для удаления
}Можно запускать эту функцию несколько раз в одном кроне или через повторяющийся Ajax запрос.