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

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

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

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

Первый шаг — понять, какие товары считаются неактивными. Обычно это товары, у которых с момента последней покупки прошло больше определённого периода (например, 6 месяцев). Однако WooCommerce по умолчанию не хранит дату последней продажи для товара, поэтому нужно получить эти данные из заказов.

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

SELECT p.ID AS product_id, MAX(o.post_date) AS last_order_date
FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_id IN (
  SELECT order_item_id FROM wp_woocommerce_order_itemmeta WHERE meta_key = '_product_id' AND meta_value = p.ID
)
LEFT JOIN wp_posts o ON o.ID = oi.order_id AND o.post_status IN ('wc-completed', 'wc-processing')
WHERE p.post_type = 'product'
GROUP BY p.ID
ORDER BY last_order_date ASC
LIMIT 10;

Этот запрос покажет 10 товаров с самыми старыми датами последних заказов. Если дата отсутствует — таких товаров не покупали.

Пошаговое решение: автоматическое отключение товаров

1. Создаем функцию для получения даты последней покупки товара

function get_last_purchase_date( $product_id ) {
    global $wpdb;
    $query = $wpdb->prepare(
        "SELECT MAX(p.post_date) FROM {$wpdb->posts} p
         INNER JOIN {$wpdb->prefix}woocommerce_order_items oi ON p.ID = oi.order_id
         INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
         WHERE p.post_type = 'shop_order'
         AND p.post_status IN ('wc-completed', 'wc-processing')
         AND oim.meta_key = '_product_id'
         AND oim.meta_value = %d",
         $product_id
    );
    return $wpdb->get_var( $query );
}

2. Функция для массового отключения товаров старше заданного периода

function disable_inactive_products( $days_inactive = 180 ) {
    $args = [
        'post_type' => 'product',
        'posts_per_page' => -1,
        'fields' => 'ids',
    ];
    $products = get_posts( $args );
    $now = current_time( 'timestamp' );
    foreach ( $products as $product_id ) {
        $last_purchase = get_last_purchase_date( $product_id );
        if ( ! $last_purchase ) {
            // Товар никогда не покупался, отключаем
            wp_update_post([
                'ID' => $product_id,
                'post_status' => 'draft'
            ]);
            continue;
        }
        $last_purchase_ts = strtotime( $last_purchase );
        if ( $now - $last_purchase_ts > DAY_IN_SECONDS * $days_inactive ) {
            wp_update_post([
                'ID' => $product_id,
                'post_status' => 'draft'
            ]);
        }
    }
}

3. Запуск процесса через WP-Cron

Чтобы отключение происходило регулярно, добавим задачу в планировщик WordPress:

if ( ! wp_next_scheduled( 'disable_inactive_products_daily' ) ) {
    wp_schedule_event( time(), 'daily', 'disable_inactive_products_daily' );
}

add_action( 'disable_inactive_products_daily', function() {
    disable_inactive_products( 180 ); // 180 дней — период неактивности
});

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

  • Выполните запрос в базе, чтобы убедиться, что статус товаров изменился на draft.
  • Через админку WooCommerce проверьте список товаров — отключённые должны быть в статусе "Черновик" и не отображаться на сайте.
  • Для теста можно уменьшить период неактивности, например, до 1 дня, и запустить функцию вручную: disable_inactive_products(1);

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

  • Товары не отключаются: проверьте права пользователя, под которым запускается WP-Cron, и нет ли ошибок в логах сервера.
  • Даты покупок не определяются: убедитесь, что в базе есть заказы со статусами wc-completed или wc-processing, и что метаполя _product_id корректно заполнены.
  • Большая нагрузка при массовом обновлении: разбейте отключение на порции, например, по 50 товаров за запуск, чтобы не перегружать сервер.

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

  • Используйте транзиенты или кеширование даты последней покупки, чтобы не выполнять тяжёлые запросы каждый раз.
  • Добавьте проверку nonce и прав доступа, если запускаете функцию вручную через админку.
  • Резервное копирование базы перед внедрением автоматического отключения — обязательный шаг.
  • Для магазинов с большим количеством заказов и товаров лучше вынести логику в отдельный WP-CLI скрипт и запускать через cron на уровне сервера.

Сравнение способов реализации автоматического отключения

МетодПлюсыМинусы
Код в functions.php + WP-CronПолный контроль, бесплатный, гибкийНагрузка на сайт, требуется тестирование
Плагин автоматизации (например, WP All Import + кастомные скрипты)Простота настройки, интерфейсПлатно, ограниченная кастомизация
WP-CLI скрипт с cron на сервереВысокая производительность, нет нагрузки на сайтТребует доступа к серверу, навыков командной строки
Как избежать конфликтов между WooCommerce и другими плагинами WordPress
23.04.2026
Автоматическое отключение неактивных товаров в WooCommerce по дате последней покупки
26.05.2026
WooCommerce: автоматическое отключение товаров по дате последней покупки
18.06.2026
Как отключить REST API в WordPress без плагинов
19.01.2026
Отложенная публикация постов в WordPress: практическое руководство
09.01.2026