wp-lessons.ru wordpress WP-Lessons

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

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

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

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

Критерии неактивности могут быть разными, например:

  • Отсутствие продаж за последний N месяцев.
  • Отсутствие обновления товара (изменения цены, описания и т.п.) за определённый период.
  • Нет просмотров или добавлений в корзину (если есть соответствующая аналитика).

В этой статье рассмотрим самый распространённый вариант — отключение товаров без продаж за последние 3 месяца.

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

Шаг 1. Создание WP-Cron задачи для периодической проверки

Добавим в functions.php вашей темы или в отдельный плагин код для регистрации задачи, которая будет запускаться раз в сутки:

function wp_lessons_schedule_deactivate_inactive_products() {
    if ( ! wp_next_scheduled( 'wp_lessons_deactivate_inactive_products_hook' ) ) {
        wp_schedule_event( time(), 'daily', 'wp_lessons_deactivate_inactive_products_hook' );
    }
}
add_action( 'wp', 'wp_lessons_schedule_deactivate_inactive_products' );

Шаг 2. Реализация функции деактивации

Создадим обработчик, который найдет товары без продаж за 90 дней и установит для них статус draft (черновик), тем самым отключая их из каталога:

add_action( 'wp_lessons_deactivate_inactive_products_hook', 'wp_lessons_deactivate_inactive_products' );
function wp_lessons_deactivate_inactive_products() {
    global $wpdb;

    $days_inactive = 90; // количество дней без продаж
    $date_cutoff = date( 'Y-m-d H:i:s', strtotime( "-{$days_inactive} days" ) );

    // Получаем ID товаров с продажами за последние 90 дней
    $sold_products = $wpdb->get_col( $wpdb->prepare(
        "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->prefix}posts as orders ON orders.ID = order_items.order_id
        
        WHERE order_item_meta.meta_key = '_product_id'
        AND orders.post_type = 'shop_order'
        AND orders.post_status IN ('wc-completed', 'wc-processing')
        AND orders.post_date >= %s",
        $date_cutoff
    ) );

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

    // Определяем товары без продаж
    $inactive_products = array_diff( $all_products, $sold_products );

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

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

Для проверки:

  • Запустите функцию вручную, вызвав do_action('wp_lessons_deactivate_inactive_products_hook'); через консоль WP-CLI или через временный вызов в коде.
  • Проверьте, что товары без продаж за последние 90 дней получили статус draft.
  • В административной панели убедитесь, что эти товары больше не отображаются как опубликованные.
  • Следите за логами (если добавите логирование), чтобы убедиться, что задача запускается по расписанию.

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

  • Неверные статусы заказов для проверки продаж. В коде учтены только wc-completed и wc-processing. Если у вас используются другие статусы, допишите их в массив.
  • Товары не деактивируются. Проверьте наличие запланированного события в WP-Cron командой wp cron event list через WP-CLI.
  • Зависание скрипта при большом количестве товаров. В таких случаях стоит реализовать постраничную обработку товаров или разбить задачу на несколько частей.
  • Отсутствие прав для изменения статуса товаров. Код должен запускаться от имени администратора, убедитесь, что контекст правильный.

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

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

Сравнение решений для автоматического отключения товаров

МетодПлюсыМинусы
Плагин (например, Product Visibility Scheduler)Удобный интерфейс, готовые настройкиДополнительная нагрузка, зависимость от стороннего кода, платные версии
Код на WP-Cron с SQL запросами (как в статье)Полный контроль, отсутствуют лишние зависимостиТребует знаний PHP и SQL, возможны ошибки при масштабировании
Отчёт и ручная деактивацияМаксимальная безопасность, простотаЗатратно по времени, требует постоянного контроля
×
Делай сайт лучше!!

-20% на премиум темы и плагины

Использовать скидку ⋙