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

Почему важно отключать неактивные товары в WooCommerce

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

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

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

  • wp_posts — товары имеют тип записи product или product_variation;
  • wp_woocommerce_order_items и wp_woocommerce_order_itemmeta — содержат данные о заказанных товарах;
  • wp_posts с типом shop_order — сами заказы, где поле post_date — дата заказа.

Поэтому задача сводится к поиску товаров, для которых не было заказов за последние N дней.

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

Добавьте следующий код в файл functions.php вашей темы или в кастомный плагин. Он будет запускаться по расписанию (cron) и менять статус товаров, не продававшихся за указанный период.

function disable_inactive_products_by_last_order() {
    global $wpdb;

    $days_inactive = 90; // Период неактивности в днях
    $date_threshold = date('Y-m-d H:i:s', strtotime("-" . $days_inactive . " days"));

    // Получаем ID товаров, у которых были продажи за последние $days_inactive дней
    $active_product_ids = $wpdb->get_col($wpdb->prepare(
        "SELECT DISTINCT order_items.order_item_id FROM {$wpdb->prefix}woocommerce_order_items AS order_items
        
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS itemmeta ON order_items.order_item_id = itemmeta.order_item_id
        INNER JOIN {$wpdb->prefix}posts AS orders ON orders.ID = order_items.order_id
        WHERE orders.post_type = 'shop_order'
        AND orders.post_status IN ('wc-completed', 'wc-processing')
        AND orders.post_date >= %s
        AND itemmeta.meta_key = '_product_id'",
        $date_threshold
    ));

    // Получаем все опубликованные товары
    $all_products = get_posts(array(
        'post_type' => array('product', 'product_variation'),
        'post_status' => 'publish',
        'numberposts' => -1,
        'fields' => 'ids',
    ));

    // Определяем неактивные товары
    $inactive_products = array_diff($all_products, $active_product_ids);

    // Меняем статус неактивных товаров на черновик
    foreach ($inactive_products as $product_id) {
        wp_update_post(array(
            'ID' => $product_id,
            'post_status' => 'draft'
        ));
    }
}

// Регистрируем ежедневное событие cron
if (!wp_next_scheduled('disable_inactive_products_event')) {
    wp_schedule_event(time(), 'daily', 'disable_inactive_products_event');
}

add_action('disable_inactive_products_event', 'disable_inactive_products_by_last_order');

Объяснение кода

  • Функция ищет ID товаров, которые были в заказах со статусом wc-completed или wc-processing за последние 90 дней.
  • Определяет все опубликованные товары и сравнивает с активными.
  • Товары, которые не продавались, переводит в статус draft, тем самым отключая их из публичного каталога.
  • Запускается ежедневно через wp-cron.

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

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

  1. Подождите или вручную запустите событие disable_inactive_products_event через плагин WP Crontrol.
  2. Перейдите в админку WooCommerce → Товары и отфильтруйте по статусу Черновик. Там должны появиться товары без заказов за последние 90 дней.
  3. Проверьте, что ранее продаваемые товары остались опубликованными.

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

  • Ошибка: Товары не отключаются.
    Причина: Некорректно работает запрос к базе, например, отличаются префиксы таблиц или заказы имеют другой статус.
    Решение: Проверьте префикс таблиц $wpdb->prefix, убедитесь, что статусы заказов совпадают с фактическими, например, добавьте wc-on-hold если нужно.
  • Ошибка: Скрипт отключает товары с недавними покупками.
    Причина: Неверно определён период или дата заказа.
    Решение: Проверьте формат даты и используйте отладку через error_log() для вывода значений переменных.
  • Ошибка: Скрипт не запускается автоматически.
    Решение: Убедитесь, что wp-cron работает (например, заходите на сайт), или настройте системный cron на вызов wp-cron.php.

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

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

Таблица сравнения вариантов решения задачи

МетодПлюсыМинусыРекомендуется для
Кастомный код (cron)Полный контроль, нет зависимостейТребует знаний PHP и SQL, возможны ошибки без тестированияСредние и крупные магазины с разработчиками
Плагины-менеджеры товаровУдобный интерфейс, дополнительные функцииМогут замедлять сайт, ограниченная гибкостьНебольшие магазины без разработчиков
Ручное отключениеПростое, без кодаТрудоёмко, не масштабируетсяМалые магазины с небольшим ассортиментом
Как удалить неиспользуемые метаполя из базы данных WordPress
04.05.2026
Как установить ограничения на размер загружаемых файлов в WordPress
25.02.2026
Автоматическое создание резервных копий WordPress: лучшие практики и решения
10.11.2025
Как отменить удаление пользователей WordPress без удаления их постов
22.02.2026
Как создать собственный шорткод в WordPress
05.11.2025