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

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

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

Автоматизация удаления неактуальных товаров позволяет:

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

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

Классические критерии отбора товаров для удаления:

  • Отсутствие заказов по товару за последние N месяцев;
  • Статус товара — «черновик», «удален» или «приватный»;
  • Товары без остатка на складе (stock = 0) и без заказов;
  • Отсутствие активности (просмотров, обновлений) за длительный период.

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

Пошаговое решение: скрипт автоматического удаления

Шаг 1. Написание функции удаления по критериям

function wpset_delete_inactive_products() {
    global $wpdb;
    // Определяем дату 6 месяцев назад
    $date_limit = date('Y-m-d H:i:s', strtotime('-6 months'));

    // Получаем ID товаров без заказов за последние 6 месяцев
    $product_ids = $wpdb->get_col($wpdb->prepare(
        "SELECT p.ID FROM {$wpdb->posts} p
        LEFT JOIN {$wpdb->prefix}woocommerce_order_items oi ON oi.order_item_name = p.ID
        LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
        LEFT JOIN {$wpdb->posts} o ON o.ID = oi.order_id
        WHERE p.post_type = 'product'
        AND (o.post_date < %s OR o.post_date IS NULL)
        AND p.ID NOT IN (
            SELECT order_item_meta.meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta
            WHERE order_item_meta.meta_key = '_product_id'
        )
        AND p.post_status = 'publish'", $date_limit
    ));

    if (empty($product_ids)) {
        return 'No inactive products found';
    }

    $deleted_count = 0;
    foreach ($product_ids as $product_id) {
        $stock = get_post_meta($product_id, '_stock', true);
        if ((int)$stock === 0) {
            wp_trash_post($product_id); // Перемещаем в корзину
            $deleted_count++;
        }
    }

    return "Deleted {$deleted_count} inactive products.";
}

Шаг 2. Запуск функции по расписанию с WP-Cron

add_action('wpset_daily_delete_inactive_products', 'wpset_delete_inactive_products');

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

Шаг 3. Ручной запуск для тестирования

add_action('admin_init', function() {
    if (isset($_GET['run_delete_inactive'])) {
        echo wpset_delete_inactive_products();
        exit;
    }
});

Для запуска вручную откройте в браузере https://ваш-сайт/wp-admin/?run_delete_inactive=1

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

  • Проверьте, что товары с нулевым остатком и без заказов за последние 6 месяцев переместились в корзину;
  • В админке WooCommerce - Товары - Корзина должны появиться удалённые записи;
  • Запустите скрипт вручную через GET-параметр и убедитесь в выводе количества удалённых товаров;
  • Контролируйте логи сервера на ошибки во время запуска WP-Cron.

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

  • Неверный подсчёт товаров без заказов: из-за сложной структуры заказов WooCommerce SQL-запрос может возвращать неверные результаты. Проверьте запрос отдельно в phpMyAdmin и корректно ли связываются таблицы.
  • Функция wp_trash_post не срабатывает: убедитесь, что у пользователя, запускающего код, есть права на удаление продуктов. Для автоматического запуска через WP-Cron права не нужны, но при ручном запуске — да.
  • WP-Cron не запускается: если сайт мало посещаем, WP-Cron может не срабатывать. Настройте системный cron на сервере для вызова wp-cron.php.
  • Удаление товаров с остатком: проверьте точность чтения метаполя _stock — иногда используется _stock_status или сторонние склады.

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

  • Перед удалением товаров лучше перемещать их в корзину, а не удалять сразу — для возможности восстановления.
  • Ограничьте частоту запуска скрипта — например, раз в сутки, чтобы не нагружать базу.
  • Для больших магазинов добавьте пагинацию в обработке ID товаров, чтобы не превышать лимиты памяти и времени выполнения скрипта.
  • Используйте wp_defer_term_counting(true) перед удалением и wp_defer_term_counting(false) после для оптимизации обновления таксономий.
  • Резервные копии базы данных обязательны перед внедрением автоматического удаления.

Сравнение методов удаления неактуальных товаров

МетодОписаниеПлюсыМинусы
Ручное удаление в админкеАдмин вручную удаляет товарыПолный контрольДолго, риск пропустить
Плагины очистки базыАвтоматизация через сторонние плагиныПростота настройкиЗависимость от стороннего кода, нагрузка
Собственный WP-Cron скриптКодовое решение под нужные критерииГибкость, точечное удалениеТребует тестирования, поддержки
Как удалить заблокированные аккаунты пользователей в WordPress
02.01.2026
WooCommerce: автоматическое отключение неактивных вариаций товаров
05.05.2026
Как установить и настроить WPRemark для расширенного комментирования в WordPress
19.02.2026
Как удалить все неактивные пользователи в WordPress с помощью кода
10.01.2026
Автоматическое удаление нерабочих вариаций товаров в WooCommerce
24.04.2026