Диагностика проблемы с заблокированными заказами в 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 |
| Ручное удаление через админку | Просто и понятно | Трудозатратно, не автоматично | Ручной выбор и удаление заказов |