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

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

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

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

Критерии для удаления:

  • Количество на складе равно нулю (_stock = 0)
  • Товар не продавался за последние 90 дней
  • Товар не имеет активных заказов в обработке

Для реализации понадобится запрос к базе данных, который позволит выбрать только те продукты, которые соответствуют этим условиям.

Пошаговое решение: автоматизация удаления товаров

1. Создание функции для выборки и удаления товаров

Добавьте следующий код в файл functions.php вашей темы или в отдельный плагин:

function wps_delete_old_out_of_stock_products() {
    if ( ! class_exists('WooCommerce') ) {
        return; // WooCommerce не активен
    }

    global $wpdb;
    $days = 90; // период в днях для проверки продаж
    $date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));

    // Получаем ID товаров с нулевым остатком
    $product_ids = $wpdb->get_col( $wpdb->prepare(
        "SELECT p.ID FROM {$wpdb->posts} p
         INNER JOIN {$wpdb->postmeta} pm_stock ON p.ID = pm_stock.post_id
         WHERE p.post_type = 'product'
           AND p.post_status = 'publish'
           AND pm_stock.meta_key = '_stock'
           AND pm_stock.meta_value = '0'"
    ));

    if ( empty($product_ids) ) {
        return;
    }

    foreach ( $product_ids as $product_id ) {
        // Проверяем дату последней продажи
        $last_order_date = $wpdb->get_var( $wpdb->prepare(
            "SELECT MAX(p.post_date) FROM {$wpdb->posts} p
             INNER JOIN {$wpdb->prefix}woocommerce_order_items oi ON oi.order_id = p.ID
             INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oim.order_item_id = oi.order_item_id
             WHERE p.post_type = 'shop_order'
               AND p.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold')
               AND oim.meta_key = '_product_id'
               AND oim.meta_value = %d",
            $product_id
        ));

        if ( ! $last_order_date || $last_order_date < $date_threshold ) {
            // Удаляем товар
            wp_delete_post( $product_id, true );
        }
    }
}

2. Настройка планового запуска

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

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

add_action( 'wps_delete_old_products_event', 'wps_delete_old_of_stock_products' );

function wps_delete_old_of_stock_products() {
    wps_delete_old_out_of_stock_products();
}

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

  1. В админке WooCommerce перейдите в раздел «Товары» и отфильтруйте по нулевому остатку.
  2. Запустите функцию вручную, например, вызвав wps_delete_old_out_of_stock_products() через WP-CLI или временно добавив вызов в functions.php.
  3. Проверьте, что товары, которые не продавались более 90 дней и имеют нулевой остаток, исчезли из каталога.
  4. Убедитесь, что товары с активными заказами или с недавними продажами остались.

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

  • Ошибка: Функция не удаляет товары.
    Причина: Неверно указан ключ метаданных или статус поста.
    Решение: Проверьте, что в базе данных товары имеют мета _stock с числовым значением, а статусы заказов совпадают с реальными в вашей системе.
  • Ошибка: Удаляются нужные товары.
    Причина: Некорректная логика выбора даты последней продажи.
    Решение: Проверьте правильность SQL-запроса на получение даты последней продажи, учитывайте все статусы заказов, которые считаются завершёнными или активными.
  • Ошибка: Крон-задача не срабатывает.
    Причина: Крон не активен или нет посещений сайта.
    Решение: Используйте WP-CLI или внешний сервис для вызова wp-cron.php или настройте системный cron на сервере.

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

  • Перед удалением рекомендуем делать резервное копирование базы данных.
  • Для больших магазинов разбивайте удаление на партии, чтобы избежать таймаутов.
  • Добавьте логирование удалённых товаров для последующего анализа.
  • Используйте wp_delete_post( $id, true ) с параметром true, чтобы удалять товары без возможности восстановления, если это необходимо.

Сравнение методов удаления

МетодПлюсыМинусы
Удаление через плагин (например, WP Bulk Delete)Простота использования, UIМеньше гибкости, нагрузка при больших объемах
Кастомный PHP-скрипт с WP-CronАвтоматизация, точный контроль, расширяемостьТребует навыков разработки, возможны ошибки в логике
Ручное удаление через админкуБезопасно, контрольТрудозатратно, не подходит для больших каталогов
Как добавить AJAX в формы WordPress без плагинов
25.02.2026
Как удалить неиспользуемые таблицы базы данных WordPress
08.12.2025
Как удалить и очистить комментарии в WordPress
18.02.2026
WooCommerce не отображает товары при фильтрации AJAX: диагностика и решение
28.04.2026
WooCommerce: как использовать хуки для изменения структуры страницы товара
29.05.2026