Диагностика проблемы: зачем и когда отключать неактивные товары
В интернет-магазинах на 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, возможны ошибки при масштабировании |
| Отчёт и ручная деактивация | Максимальная безопасность, простота | Затратно по времени, требует постоянного контроля |