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

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

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

Определение критериев неактивного товара

Для автоматизации важно чётко задать критерии, по которым товар считается неактивным:

  • Отсутствие продаж за определённый период (например, 6 месяцев);
  • Дата последнего обновления товара старше заданного срока;
  • Товар не находится в статусе «черновик» или «в ожидании» (то есть опубликован).

В WooCommerce продажи фиксируются через записи заказов, а дата обновления товара хранится в post_modified.

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

Ниже пример функции, которую можно добавить в functions.php или создать небольшой плагин. Функция будет запускаться по расписанию и удалять товары, не продававшиеся более 180 дней.

<?php
// Создаём событие Cron при активации плагина или темы
if (!wp_next_scheduled('wc_delete_inactive_products_event')) {
    wp_schedule_event(time(), 'daily', 'wc_delete_inactive_products_event');
}

// Хук на выполнение события
add_action('wc_delete_inactive_products_event', 'wc_delete_inactive_products');

function wc_delete_inactive_products() {
    global $wpdb;
    $threshold_days = 180; // 180 дней без продаж
    $date_threshold = date('Y-m-d H:i:s', strtotime("-{$threshold_days} days"));

    // Получаем ID продуктов, которые:
    // 1) опубликованы
    // 2) не продавались после $date_threshold
    // 3) обновлялись до $date_threshold

    $query = $wpdb->prepare(
        "SELECT p.ID FROM {$wpdb->posts} p
         WHERE p.post_type = 'product'
           AND p.post_status = 'publish'
           AND p.post_modified < %s
           AND p.ID NOT IN (
               SELECT DISTINCT order_item_meta.meta_value
               FROM {$wpdb->prefix}woocommerce_order_items as order_items
               INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
               INNER JOIN {$wpdb->posts} as 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 >= %s
           )",
        $date_threshold,
        $date_threshold
    );

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

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

    foreach ($product_ids as $product_id) {
        wp_trash_post($product_id); // Отправляем товар в корзину для удаления
    }
}

// Для очистки cron при деактивации
register_deactivation_hook(__FILE__, function() {
    wp_clear_scheduled_hook('wc_delete_inactive_products_event');
});

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

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

  • Добавьте временный лог в функцию wc_delete_inactive_products, например, через error_log(), чтобы видеть, какие ID удаляются.
  • Запустите событие вручную, вызвав do_action('wc_delete_inactive_products_event'); через консоль WP-CLI (wp eval 'do_action("wc_delete_inactive_products_event");').
  • Проверьте, что товары, соответствующие критериям, переместились в корзину (Trash) в админке WooCommerce.

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

  • Ничего не удаляется: возможно, условие выборки не срабатывает из-за неверного формата дат или статусов заказов. Проверьте, что заказы имеют статусы wc-completed или wc-processing.
  • Удаляются нужные товары: проверьте правильность условия на дату обновления и продажи, можно временно увеличить период или вывести список ID для проверки.
  • Проблемы с производительностью при большом каталоге: разбейте удаление на порции, добавьте лимит в SQL-запрос или используйте транзакции.

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

  • Всегда используйте wp_trash_post(), чтобы иметь возможность восстановить товар из корзины, а не удаляйте сразу навсегда.
  • Запускайте удаление в ночное время через Cron, чтобы не нагружать сервер в часы пик.
  • Перед массовым удалением сделайте резервную копию базы данных.
  • Добавьте логирование удалённых товаров в отдельный файл для аудита.
  • Для больших магазинов используйте пагинацию в запросе и удаляйте партиями, например по 50 товаров за одну итерацию.

Сравнение вариантов автоматического удаления неактивных товаров

МетодПлюсыМинусыКомпромисс
Плагин автоматизацииУдобный интерфейс, поддержкаМожет быть тяжёлым, платнымИспользовать проверенные плагины с минимальным функционалом
Код в functions.phpЛёгкий, кастомный, без нагрузкиТребует навыков, нет интерфейсаДобавить простой лог и возможность включать/выключать через опцию
Удаление вручную через админкуБезопасно, контролируемоТрудозатратно, не автоматичноИспользовать для мелких магазинов или точечных случаев
Автоматизация создания и удаления пользовательских метаполей в WordPress
10.04.2026
Как использовать Metabox в WordPress для создания настроек
11.12.2025
WordPress отладка проблем с кэшем и кэш-плагинами: практические решения
08.12.2025
Оптимизация базы данных WordPress: как правильно ускорить сайт
23.12.2025
Как создать автоматический импорт постов по RSS в WordPress
05.02.2026