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

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

В интернет-магазинах на WooCommerce с течением времени накапливаются товары, которые не продаются. Это увеличивает нагрузку на базу данных, замедляет работу админки и мешает управлению каталогом. Часто администраторы не замечают неактивные товары и не удаляют их вручную, особенно при большом ассортименте.

Основные признаки проблемы:

  • Замедление отображения списка товаров в админке;
  • Увеличение размера базы данных;
  • Наличие товаров без заказов за последние 30, 60 или 90 дней;
  • Затруднения в управлении каталогом из-за большого количества неактивных позиций.

Как определить товары без заказов за период

Для начала нужно понять, какие товары не продавались за определённый период. Для этого можно использовать SQL-запрос к базе WooCommerce или WP_Query с мета-запросом, но проще и эффективнее — написать кастомный код на PHP с использованием WooCommerce API.

function get_unsold_products( $days = 30 ) {
    global $wpdb;
    $date_limit = date('Y-m-d H:i:s', strtotime("-" . intval($days) . " days"));
    $query = $wpdb->prepare(
        "SELECT p.ID FROM {$wpdb->posts} p
        LEFT JOIN {$wpdb->prefix}woocommerce_order_items oi ON p.ID = oi.order_item_id
        LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
        LEFT JOIN {$wpdb->posts} o ON oi.order_id = o.ID AND o.post_type = 'shop_order' AND o.post_status IN ('wc-completed', 'wc-processing')
        WHERE p.post_type = 'product' AND p.post_status = 'publish'
        AND (o.post_date IS NULL OR o.post_date < %s)
        GROUP BY p.ID",
        $date_limit
    );
    return $wpdb->get_col( $query );
}

Этот код возвращает ID товаров, которые не продавались в течение указанного периода.

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

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

Используем стандартную функцию wp_delete_post() для удаления товаров по ID.

function delete_unsold_products( $days = 30 ) {
    $products = get_unsold_products( $days );
    foreach ( $products as $product_id ) {
        wp_delete_post( $product_id, true ); // true - удаление без перемещения в корзину
    }
    return count( $products );
}

2. Настройка WP-Cron для автоматического запуска

Добавим событие, которое будет запускать удаление товаров раз в неделю.

if ( ! wp_next_scheduled( 'wc_delete_unsold_products_weekly' ) ) {
    wp_schedule_event( time(), 'weekly', 'wc_delete_unsold_products_weekly' );
}

add_action( 'wc_delete_unsold_products_weekly', function() {
    $deleted_count = delete_unsold_products( 30 ); // удаляем товары без заказов за 30 дней
    error_log( "WooCommerce: удалено товаров без заказов - {$deleted_count}" );
});

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

Чтобы убедиться, что удаление работает:

  • Проверьте логи сервера (error_log) на наличие сообщений о количестве удалённых товаров.
  • В админке WooCommerce сравните количество товаров до и после запуска задачи.
  • Для ручного теста вызовите функцию delete_unsold_products(30) через wp shell или временный шаблон.

Частые ошибки и как исправить

  • Отсутствие заданного интервала запуска WP-Cron: Проверьте, что в WordPress включён WP-Cron и задача запланирована (wp cron event list). Если нет — добавьте вручную или настройте системный cron, чтобы вызывать wp cron.
  • Неправильный SQL-запрос: Убедитесь, что таблицы и префиксы совпадают с вашей установкой, а статус заказов правильный (wc-completed, wc-processing).
  • Удаление товаров с заказами: Проверьте, что условие корректно исключает товары с покупками за указанный период.
  • Отсутствие прав у пользователя/скрипта: Убедитесь, что PHP-скрипт имеет права на удаление постов.

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

  • Резервное копирование: Перед автоматическим удалением товаров настройте регулярный бэкап базы данных.
  • Логирование действий: Ведите лог удалённых товаров для аудита и восстановления при ошибках.
  • Пакетное удаление: Если товаров много, реализуйте удаление по партиям (например, по 20 товаров за раз) с паузами, чтобы не перегружать сервер.
  • Тестирование на staging-сервере: Перед применением на боевом сайте тестируйте скрипт на копии сайта.

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

МетодОписаниеПлюсыМинусы
Ручное удаление из админкиУдаление товаров по фильтру без заказовПростота, контрольТрудозатратно, не автоматично
Плагин (например, WP Bulk Delete)Фильтрация и удаление товаров по критериямГрафический интерфейс, гибкостьМожет быть избыточным, нагрузка
Кастомный код через WP-CronАвтоматическое удаление по расписаниюАвтоматизация, тонкий контрольНеобходим опыт, возможные ошибки без тестов
Как создать автоматический бэкап базы данных WordPress на WPengine
03.01.2026
WooCommerce: решение проблемы не работающих вариативных атрибутов в описании товара
16.05.2026
Как создать свой плагин для WordPress с нуля
12.11.2025
Как использовать Object Cache в WordPress для улучшения производительности
05.02.2026
Оптимизация базы данных WordPress для ускорения работы сайта
23.12.2025