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

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

В магазине на WooCommerce может накапливаться большое количество товаров, которые никогда не были куплены. Это влияет на производительность, усложняет управление каталогом и может ухудшать пользовательский опыт. Автоматическое удаление таких товаров за выбранный период (например, 6 месяцев или год) помогает поддерживать каталог в актуальном состоянии без ручного контроля.

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

Чтобы удалить товары без заказов, нужно сначала получить их список. Для этого понадобится SQL-запрос или WP_Query, объединяющий информацию из таблиц заказов WooCommerce и постов товаров.

Пример SQL-запроса для получения ID товаров без продаж за последние 6 месяцев:

SELECT p.ID FROM {$wpdb->prefix}posts p
LEFT JOIN (
  SELECT order_item_meta.meta_value AS product_id
  FROM {$wpdb->prefix}woocommerce_order_items order_items
  INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
  INNER JOIN {$wpdb->prefix}posts posts ON posts.ID = order_items.order_id
  WHERE order_item_meta.meta_key = '_product_id'
    AND posts.post_type = 'shop_order'
    AND posts.post_status IN ('wc-completed', 'wc-processing')
    AND posts.post_date > DATE_SUB(NOW(), INTERVAL 6 MONTH)
) sold_products ON sold_products.product_id = p.ID
WHERE p.post_type = 'product'
  AND sold_products.product_id IS NULL
  AND p.post_status = 'publish';

Этот запрос выбирает товары, у которых нет заказов со статусом wc-completed или wc-processing за последние 6 месяцев.

Пошаговое решение: автоматизация удаления через WP-Cron

1. Создаем функцию для удаления товаров без продаж

function wpbit_delete_unsold_products() {
    global $wpdb;

    $query = "SELECT p.ID FROM {$wpdb->posts} p
    LEFT JOIN (
      SELECT order_item_meta.meta_value AS product_id
      FROM {$wpdb->prefix}woocommerce_order_items order_items
      INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
      INNER JOIN {$wpdb->posts} posts ON posts.ID = order_items.order_id
      WHERE order_item_meta.meta_key = '_product_id'
        AND posts.post_type = 'shop_order'
        AND posts.post_status IN ('wc-completed', 'wc-processing')
        AND posts.post_date > DATE_SUB(NOW(), INTERVAL 6 MONTH)
    ) sold_products ON sold_products.product_id = p.ID
    WHERE p.post_type = 'product'
      AND sold_products.product_id IS NULL
      AND p.post_status = 'publish';";

    $product_ids = $wpdb->get_col($query);

    if (!empty($product_ids)) {
        foreach ($product_ids as $product_id) {
            wp_delete_post($product_id, true); // true - удаляет без возможности восстановления
        }
    }
}

2. Регистрируем событие WP-Cron для регулярного запуска

if (!wp_next_scheduled('wpbit_daily_delete_unsold_products')) {
    wp_schedule_event(time(), 'daily', 'wpbit_daily_delete_unsold_products');
}

add_action('wpbit_daily_delete_unsold_products', 'wpbit_delete_unsold_products');

3. Альтернативно: запускать вручную для теста

Для проверки можно вызвать функцию напрямую из файла темы или плагина:

add_action('init', function() {
    if (current_user_can('administrator') && isset($_GET['delete_unsold'])) {
        wpbit_delete_unsold_products();
        echo 'Удаление товаров без заказов выполнено';
        exit;
    }
});

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

  • Посмотрите в админке WooCommerce - раздел "Товары". Товары без заказов за последние 6 месяцев должны исчезнуть.
  • Проверьте, что при наличии заказов статусом wc-completed или wc-processing за 6 месяцев товар остается.
  • Для полного контроля смотрите логи (если настроены) или добавьте логирование в функцию удаления.

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

  • Ошибка: Товары не удаляются — проверьте права пользователя и что WP-Cron запускается.
    Решение: Удостоверьтесь, что cron-событие активировано и сервер поддерживает WP-Cron. Для отладки используйте плагин WP Crontrol.
  • Ошибка: Удаляются товары с заказами.
    Решение: Проверьте правильность SQL-запроса и статусы заказов — могут быть другие статусы, которые нужно учитывать (например, wc-on-hold).
  • Ошибка: Производительность падает при большом каталоге.
    Решение: Разбивайте запросы на части, используйте WP_Query с пагинацией, кешируйте результаты.

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

  • Перед удалением делайте резервные копии базы данных.
  • Включайте удаление только по статусу publish, чтобы не трогать черновики и архивные товары.
  • Используйте транзакции или проверяйте ошибки при удалении.
  • Для больших магазинов используйте WP-CLI для запуска команд удаления вне веб-сессий.
  • Добавьте логирование удаленных товаров для аудита.

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

МетодПлюсыМинусыКогда использовать
SQL-запрос + wp_delete_post + WP-CronГибко, полностью под контролем, без сторонних плагиновТребует аккуратности, знание SQL, возможны ошибки при обновлениях WooCommerceДля разработчиков с опытом, когда нужен точный контроль
Плагин очистки каталогаПростота, готовое решениеМогут быть ограничения, нагрузка, меньше контроляДля быстрого решения без программирования
WP-CLI скриптыВысокая производительность, без нагрузки на сайтТребует доступа к серверу и командной строкеБольшие магазины, администраторы с SSH-доступом
Как добавить автоматическое сохранение в формы WordPress
04.01.2026
Как удалить или заблокировать регистрацию пользователей в WordPress
09.01.2026
Автоматизация обновления подписок в WordPress через AJAX
21.01.2026
Как установить и очистить очередь AJAX в WordPress для улучшения производительности
27.03.2026
Автоматическое удаление пустых комментариев в WordPress
03.02.2026