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

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

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

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

Для начала нужно понять, какие товары не имеют связанных заказов за последние N дней. В WooCommerce связь между товарами и заказами хранится в таблицах wp_woocommerce_order_items и wp_woocommerce_order_itemmeta, а сами заказы — в wp_posts с типом shop_order. Это важно для правильного поиска.

Пример SQL запроса для проверки

SELECT p.ID, p.post_title FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_name = p.ID::text
LEFT JOIN wp_posts o ON o.ID = oi.order_id AND o.post_type = 'shop_order' AND o.post_status IN ('wc-completed', 'wc-processing')
WHERE p.post_type = 'product'
AND o.ID IS NULL
AND p.post_date < DATE_SUB(NOW(), INTERVAL 30 DAY);

Этот запрос — концептуальный, требует доработки под вашу структуру и префиксы таблиц. Он показывает товары без заказов за последние 30 дней.

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

Построим простое решение в виде функции, которая будет запускаться ежедневно и удалять товары без заказов за 30 дней.

Шаг 1. Добавляем функцию удаления в functions.php или плагин

function wc_delete_products_without_orders() {
    global $wpdb;
    $interval_days = 30;

    // Получаем ID товаров без заказов за последние $interval_days дней
    $product_ids = $wpdb->get_col($wpdb->prepare(
        "SELECT p.ID FROM {$wpdb->posts} p
         WHERE p.post_type = 'product'
           AND p.post_status = 'publish'
           AND p.post_date < NOW() - INTERVAL %d DAY
           AND NOT EXISTS (
               SELECT 1 FROM {$wpdb->prefix}woocommerce_order_items oi
               JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
               JOIN {$wpdb->posts} o ON oi.order_id = o.ID
               WHERE o.post_type = 'shop_order'
                 AND o.post_status IN ('wc-completed', 'wc-processing')
                 AND oim.meta_key = '_product_id'
                 AND oim.meta_value = p.ID
           )",
         $interval_days
    ));

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

Шаг 2. Планируем запуск через WP-Cron

if (!wp_next_scheduled('wc_daily_delete_products')) {
    wp_schedule_event(time(), 'daily', 'wc_daily_delete_products');
}
add_action('wc_daily_delete_products', 'wc_delete_products_without_orders');

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

  • Запустите функцию вручную через wc_delete_products_without_orders() или дождитесь запланированного запуска.
  • Проверьте, что товары без заказов старше 30 дней удалены из базы (через админку или SQL).
  • Просмотрите логи ошибок, чтобы убедиться, что ошибок при удалении нет.
  • Для тестирования можно изменить интервал на меньший (например, 1 день) и создать тестовый товар без заказов.

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

  • Неправильные префиксы таблиц: используйте $wpdb->prefix и $wpdb->posts вместо жестко вписанных имен.
  • Удаление товаров с заказами в статусе 'on-hold' или 'pending': убедитесь, что в запросе фильтруются только финализированные статусы wc-completed и wc-processing.
  • Отсутствие WP-Cron: если на сайте мало трафика, WP-Cron может не запускаться регулярно. Настройте системный cron или запускайте вручную.
  • Потеря данных: всегда делайте резервную копию базы перед массовым удалением!

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

  • Используйте wp_delete_post($id, true) для полного удаления, включая метаданные.
  • Ограничьте количество удаляемых товаров за один запуск, например, добавив LIMIT 50 в запрос и циклический запуск, чтобы избежать таймаутов.
  • Логируйте удалённые ID в отдельный файл для аудита.
  • Регулярно проверяйте таблицы WooCommerce на наличие устаревших данных и оптимизируйте их.
  • Для больших магазинов рассмотрите запуск удаления в CLI скриптах или с помощью wp-cli для надежности.

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

СпособПреимуществаНедостаткиПример
WP-Cron с кастомным кодом Гибкость, контроль, бесплатное решение Зависит от посещений сайта, требует тестирования Код из статьи
Плагины для очистки каталога Простой интерфейс, готовые решения Могут быть платными, не всегда гибкие WP Sweep, Advanced Database Cleaner
Ручное удаление через админку Безопасно, без риска ошибки кода Неэффективно для больших магазинов WooCommerce > Товары > Фильтры
Как создать собственный виджет в WordPress: подробное руководство с примерами
22.11.2025
Как использовать WPCommunity для создания социальной сети на WordPress
06.01.2026
Как автоматизировать управление переадресациями в WordPress
05.04.2026
Оптимизация WordPress для быстрой загрузки сайта: практические методы и примеры
05.11.2025
Как использовать REST API в WordPress для создания плагинов
25.11.2025