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

Проблема: автоматическое управление видимостью товаров с нулевым остатком в WooCommerce

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

Диагностика проблемы

Чтобы понять, что товары с нулевым остатком не отключаются автоматически, нужно:

  • Проверить, включен ли на уровне WooCommerce параметр управления запасами (WooCommerce → Настройки → Товары → Запасы).
  • Убедиться, что у товаров и вариаций активен контроль запасов и доступны остатки.
  • Оценить, отключается ли товар вручную при нулевом остатке.
  • Посмотреть, не влияют ли кастомные функции или плагины на логику видимости товаров.

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

SELECT p.ID, p.post_title, pm.meta_value as stock FROM wp_posts p
LEFT JOIN wp_postmeta pm ON p.ID = pm.post_id AND pm.meta_key = '_stock'
WHERE p.post_type IN ('product', 'product_variation')
AND pm.meta_value = '0'
AND p.post_status = 'publish';

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

Реализуем PHP-функцию, которая будет запускаться по крону или хук-событию, проверять остатки и менять статус на draft (отключенный) у товаров и вариаций с нулевым запасом. Это позволит не удалять товары, а просто скрывать их из каталога.

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

function wpexperts_disable_out_of_stock_products() {
    // Получаем все товары и вариации с нулевым запасом и статусом publish
    $args = [
        'post_type'      => ['product', 'product_variation'],
        'posts_per_page' => -1,
        'meta_query'     => [
            [
                'key'     => '_stock',
                'value'   => '0',
                'compare' => '=',
            ],
        ],
        'post_status'    => 'publish',
        'fields'         => 'ids',
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        foreach ($query->posts as $product_id) {
            // Меняем статус на draft
            wp_update_post([
                'ID'          => $product_id,
                'post_status' => 'draft',
            ]);
        }
    }
}

2. Запуск функции по расписанию с помощью WP-Cron

Добавим расписание для регулярного вызова функции, например, раз в час:

if (!wp_next_scheduled('wpexperts_hourly_stock_check')) {
    wp_schedule_event(time(), 'hourly', 'wpexperts_hourly_stock_check');
}

add_action('wpexperts_hourly_stock_check', 'wpexperts_disable_out_of_stock_products');

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

Для проверки, что функция работает корректно:

  • Убедитесь, что товары и вариации с нулевым остатком автоматически изменили статус на draft.
  • Проверьте в админке WooCommerce → Товары, что эти товары не отображаются среди опубликованных.
  • С помощью SQL-запроса из раздела диагностики убедитесь, что среди опубликованных товаров не осталось с нулевым запасом.
  • Проверьте на фронтенде магазина, что товары с нулевым остатком не доступны для покупки и не видны посетителям.

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

  • Функция не запускается по расписанию. Проверьте, активирован ли WP-Cron и не отключен ли он в wp-config.php (DISABLE_WP_CRON должен быть false или не задан).
  • Товары не меняют статус. Убедитесь, что функция вызывается и что у пользователя, под которым выполняется код, есть права на редактирование товаров.
  • Нулевой остаток не учитывается. Проверьте, что у всех товаров и вариаций включен контроль запасов и корректно заполнено поле _stock.
  • Товары с вариациями остаются опубликованными, хотя у вариаций нулевой запас. В данном решении отключаются и вариации, и товары отдельно. Для более точной логики можно расширить функцию, чтобы отключать родительский товар, если все вариации отсутствуют в наличии.

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

  • Оптимизация запросов. При большом количестве товаров стоит использовать пагинацию в WP_Query, чтобы не нагружать сервер.
  • Логирование изменений. Добавьте логирование отключенных товаров для аудита:
    error_log('Отключен товар ID: ' . $product_id);
  • Защита от случайного отключения. Рекомендуется тестировать функцию сначала на тестовом сайте или использовать дополнительное условие, например, отключать только если остаток 0 и дата последнего заказа более чем 7 дней назад.
  • Резервное копирование. Перед внедрением автоматических изменений всегда делайте резервную копию базы данных.

Сравнение вариантов реализации

ВариантПлюсыМинусы
Плагин управления запасамиГотовое решение, поддержка, настройки без кодаДополнительная нагрузка, ограничение гибкости, возможные конфликты
Собственный код (описанный выше)Полный контроль, легковесность, кастомизацияТребует навыков программирования, необходимость тестирования
Ручное отключениеПростота, нет риска ошибок кодаНеэффективно при большом каталоге, человеческий фактор
Как создать и использовать собственные категории для AJAX-запросов в WordPress
21.11.2025
Как использовать AJAX в WordPress для форм и фильтров
26.12.2025
Как использовать хук pre_get_posts для фильтрации запросов в WordPress
19.12.2025
Как создать собственный Post Type в WordPress
26.11.2025
WooCommerce: автоматическое изменение стоимости и отключение товаров при нулевом остатке
09.07.2026