Проблема: как автоматически удалять неактивные заказы в WooCommerce
В магазинах на WooCommerce со временем накапливаются заказы в статусах, которые не были завершены или оплачены, например, «в ожидании оплаты» или «отменён». Это приводит к засорению базы данных и замедлению работы сайта. Ручное удаление неудобно и ошибочно. Задача — настроить автоматическое удаление таких заказов по расписанию с помощью стандартного WP-Cron, без сторонних плагинов.
Диагностика проблемы
Для начала нужно выявить, какие статусы заказов считаются неактивными и требуют удаления. Обычно это:
pending— ожидает оплаты;failed— оплата не прошла;cancelled— отменён пользователем или админом;on-hold— ожидает подтверждения.
Проверить, сколько таких заказов в базе, можно SQL-запросом:
SELECT COUNT(*) FROM wp_posts WHERE post_type = 'shop_order' AND post_status IN ('wc-pending', 'wc-failed', 'wc-cancelled', 'wc-on-hold');Также важно понять, за какой период заказы считаются старыми и подлежат удалению. Обычно это 7 или 14 дней с момента создания.
Пошаговое решение: настройка автоматического удаления заказов
1. Создаём функцию удаления заказов
Добавьте следующий код в файл functions.php вашей дочерней темы или в кастомный плагин:
function wpassist_delete_old_inactive_orders() {
$days = 14; // количество дней для хранения неактивных заказов
$statuses = array('wc-pending', 'wc-failed', 'wc-cancelled', 'wc-on-hold');
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$args = array(
'post_type' => 'shop_order',
'post_status' => $statuses,
'date_query' => array(
array(
'before' => $date_threshold,
'column' => 'post_date',
),
),
'posts_per_page' => -1,
'fields' => 'ids',
'no_found_rows' => true,
);
$orders = get_posts($args);
if (!empty($orders)) {
foreach ($orders as $order_id) {
wp_delete_post($order_id, true); // Полное удаление без корзины
}
}
}2. Регистрируем WP-Cron событие
Чтобы задача запускалась ежедневно, добавьте в functions.php:
function wpassist_schedule_order_deletion() {
if (!wp_next_scheduled('wpassist_daily_delete_orders')) {
wp_schedule_event(time(), 'daily', 'wpassist_daily_delete_orders');
}
}
add_action('wp', 'wpassist_schedule_order_deletion');
add_action('wpassist_daily_delete_orders', 'wpassist_delete_old_inactive_orders');3. Очистка при деактивации плагина или темы
Чтобы избежать множества запланированных задач, рекомендуется удалить расписание при деактивации:
function wpassist_clear_scheduled_order_deletion() {
$timestamp = wp_next_scheduled('wpassist_daily_delete_orders');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wpassist_daily_delete_orders');
}
}
register_deactivation_hook(__FILE__, 'wpassist_clear_scheduled_order_deletion');Проверка результата после внедрения
- В базе данных
wp_postsколичество заказов с указанными статусами и датой создания старше 14 дней должно уменьшиться. - Проверьте журнал ошибок PHP (если включён), чтобы убедиться, что функция запускается без ошибок.
- Для теста можно временно уменьшить
$daysдо 0 или 1, чтобы увидеть, что заказы удаляются сразу. - Запустите вручную функцию из админки или через WP CLI
wp eval 'wpassist_delete_old_inactive_orders();'для проверки.
Частые ошибки и как их исправить
- WP-Cron не срабатывает: Проверьте, что на сайте есть трафик, так как WP-Cron запускается по посещениям. Для автоматизации используйте системный cron, вызывающий
wp-cron.php. - Заказы не удаляются: Убедитесь, что статусы заказов указаны с префиксом
wc-и совпадают с текущими статусами WooCommerce. - Удаляются не те заказы: Проверьте условие даты и статусов — возможно, стоит использовать
post_modifiedвместоpost_dateили добавить дополнительные проверки. - Ошибка прав доступа: Для удаления заказов функция должна запускаться с правами администратора или из контекста, где доступ к базе открыт.
Практические советы по безопасности и производительности
- Безопасность: Удаление заказов — критичная операция. Рекомендуется делать резервное копирование базы перед внедрением.
- Производительность: При большом количестве заказов разбивайте удаление на партии, чтобы избежать таймаутов:
function wpassist_delete_old_inactive_orders_batch() {
$days = 14;
$statuses = array('wc-pending', 'wc-failed', 'wc-cancelled', 'wc-on-hold');
$batch_size = 50;
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$args = array(
'post_type' => 'shop_order',
'post_status' => $statuses,
'date_query' => array(
array(
'before' => $date_threshold,
'column' => 'post_date',
),
),
'posts_per_page' => $batch_size,
'fields' => 'ids',
'no_found_rows' => true,
);
$orders = get_posts($args);
if (empty($orders)) {
return;
}
foreach ($orders as $order_id) {
wp_delete_post($order_id, true);
}
}- Добавьте логирование действий, чтобы отслеживать удалённые заказы.
- Проверяйте совместимость с плагинами резервного копирования и кэширования, которые могут блокировать удаление.
Сравнение решений: плагин vs кастомный код
| Критерий | Плагин | Кастомный код (WP-Cron) | Компромисс |
|---|---|---|---|
| Управление | Удобный интерфейс | Требует редактирования кода | Больше контроля, но сложнее |
| Нагрузка на сервер | Может добавлять нагрузку | Оптимизирован под сайт | Код можно адаптировать под нагрузку |
| Гибкость | Ограничена функционалом плагина | Максимальная, под любые задачи | Код требует поддержки |
| Безопасность | Зависит от автора плагина | Контроль за всеми операциями | Требует знаний разработки |