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

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

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

Как определить товары без продаж за последние 30 дней

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

SQL-запрос для проверки товаров без продаж

SELECT p.ID, p.post_title FROM wp_posts p
WHERE p.post_type = 'product'
AND p.ID NOT IN (
    SELECT order_item_meta.meta_value FROM wp_woocommerce_order_items order_items
    JOIN wp_woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
    JOIN wp_posts orders ON orders.ID = order_items.order_id
    WHERE order_item_meta.meta_key = '_product_id'
    AND orders.post_status IN ('wc-completed', 'wc-processing')
    AND orders.post_date > DATE_SUB(NOW(), INTERVAL 30 DAY)
);

Этот запрос вернет список ID и названий товаров, которые не продавались последние 30 дней.

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

Оптимальный способ — создать WP-Cron задачу, которая будет запускаться ежедневно и удалять товары без продаж за 30 дней.

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

function wpt_delete_old_unsold_products() {
    global $wpdb;
    // Получаем ID товаров без продаж за 30 дней
    $product_ids = $wpdb->get_col(
        "SELECT p.ID FROM {$wpdb->posts} p
        WHERE p.post_type = 'product'
        AND p.post_status = 'publish'
        AND p.ID NOT IN (
            SELECT order_item_meta.meta_value FROM {$wpdb->prefix}woocommerce_order_items order_items
            JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
            JOIN {$wpdb->posts} orders ON orders.ID = order_items.order_id
            WHERE order_item_meta.meta_key = '_product_id'
            AND orders.post_status IN ('wc-completed', 'wc-processing')
            AND orders.post_date > DATE_SUB(NOW(), INTERVAL 30 DAY)
        )"
    );

    if (empty($product_ids)) {
        return; // Нет товаров для удаления
    }

    foreach ($product_ids as $product_id) {
        wp_delete_post($product_id, true); // Полное удаление
    }
}

2. Регистрируем WP-Cron задачу

function wpt_schedule_delete_old_products() {
    if (!wp_next_scheduled('wpt_daily_delete_old_products')) {
        wp_schedule_event(time(), 'daily', 'wpt_daily_delete_old_products');
    }
}
add_action('wp', 'wpt_schedule_delete_old_products');
add_action('wpt_daily_delete_old_products', 'wpt_delete_old_unsold_products');

3. Запуск задачи вручную (для теста)

// Для проверки запускаем так:
// wpt_delete_old_unsold_products();

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

  • Выполните SQL-запрос из раздела диагностики до и после запуска скрипта — количество товаров без продаж должно уменьшиться.
  • Проверьте раздел «Товары» в админке WooCommerce — старые неактивные товары должны исчезнуть.
  • Логи сервера или плагина для отладки WP-Cron покажут события запуска.

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

  • Ошибка: Товары не удаляются.
    Причина: WP-Cron не срабатывает из-за отсутствия трафика или блокировки.
    Решение: Настройте системный cron или используйте плагин для управления cron задачами, например WP Control.
  • Ошибка: Удаляются товары, которые недавно были проданы.
    Причина: Неправильный диапазон дат или статусы заказов.
    Решение: Проверьте, что в запросе правильно указаны статусы wc-completed и wc-processing, а дата сравнивается с текущим временем.
  • Ошибка: Удаляются товары со статусом draft или private.
    Причина: В запросе не фильтруется статус publish.
    Решение: Добавьте AND p.post_status = 'publish' в запрос.

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

  • Перед удалением делайте резервную копию базы данных, чтобы избежать потери данных.
  • Удаление большого числа товаров может замедлить сайт — выполняйте задачу в период минимальной нагрузки.
  • Добавьте логирование удаленных товаров для аудита, например, записывая ID и дату удаления в отдельный файл или таблицу.
  • Если магазин большой, разбивайте удаление на партии по 50-100 товаров, чтобы избежать таймаута PHP.

Таблица сравнения методов удаления старых товаров

МетодПлюсыМинусыПодходит для
Ручное удаление в админкеПросто, без кодаТрудоемко, не масштабируетсяМалые магазины
SQL запрос с удалениемБыстрое выполнениеРиск ошибок, требует навыков SQLОпытные администраторы
Автоматизация через WP-Cron (код)Автоматически поддерживает каталог актуальнымНужен контроль cron и логированиеСредние и крупные магазины
Автоматическое удаление старых корзин в WooCommerce
03.07.2026
Как создать динамическую навигацию в WordPress: примеры и пошаговое руководство
21.11.2025
WooCommerce: как отключить автоматический пересчет стоимости товаров в корзине
10.07.2026
Как отключить редактор Gutenberg в WordPress 5.9: практические способы и примеры
08.03.2026
Как оптимизировать производительность WordPress с помощью плагинов и кода
18.11.2025