WooCommerce: автоматическое удаление товаров без заказов

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

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

Как определить товары без заказов

Для того чтобы удалить товары без заказов, необходимо сначала точно определить, какие товары не были проданы ни разу. WooCommerce хранит данные о заказах в таблицах wp_posts (заказы — тип записи shop_order) и wp_woocommerce_order_items (позиции товаров в заказах).

Простейший способ — запросить ID товаров, не встречающихся в позициях заказов:

SELECT p.ID FROM wp_posts p
WHERE p.post_type = 'product'
AND p.ID NOT IN (
  SELECT order_item_meta.meta_value FROM wp_woocommerce_order_items items
  JOIN wp_woocommerce_order_itemmeta order_item_meta ON items.order_item_id = order_item_meta.order_item_id
  WHERE items.order_item_type = 'line_item'
  AND order_item_meta.meta_key = '_product_id'
);

Этот запрос возвращает ID товаров без заказов. Но для автоматизации потребуется PHP-скрипт.

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

1. Создаем WP-CLI команду для удаления

WP-CLI — удобный инструмент для автоматизации задач. Вот пример команды для удаления товаров без заказов старше определенного времени (например, 90 дней):

if ( defined('WP_CLI') && WP_CLI ) {
    WP_CLI::add_command('wc-delete-unused-products', function($args, $assoc_args) {
        $days = isset($assoc_args['days']) ? intval($assoc_args['days']) : 90;
        $date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));

        global $wpdb;

        $product_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT p.ID FROM {$wpdb->posts} p
            WHERE p.post_type = 'product'
            AND p.post_date < %s
            AND p.ID NOT IN (
                SELECT DISTINCT order_item_meta.meta_value FROM {$wpdb->prefix}woocommerce_order_items items
                JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON items.order_item_id = order_item_meta.order_item_id
                WHERE items.order_item_type = 'line_item'
                AND order_item_meta.meta_key = '_product_id'
            )",
            $date_threshold
        ));

        $count = 0;
        foreach ($product_ids as $product_id) {
            wp_delete_post($product_id, true); // true — безвозвратно
            $count++;
        }

        WP_CLI::success("Удалено товаров без заказов старше {$days} дней: {$count}");
    });
}

2. Запуск команды

После добавления кода в файл плагина или в functions.php темы, запустите из терминала в корне сайта:

wp wc-delete-unused-products --days=90

Это удалит все товары без заказов, которые были созданы более 90 дней назад. Параметр --days можно менять.

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

  • Перед запуском выполните полный бэкап базы данных.
  • Запустите SQL-запрос из раздела диагностики и сравните количество ID товаров до и после.
  • Проверьте в админке WooCommerce список товаров — удаленные должны исчезнуть.
  • Для теста можно создать тестовый товар без заказов старше 90 дней (через изменение даты публикации) и проверить, удаляется ли он.

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

  • Ошибка: Нет доступа к WP-CLI или команда не распознается.
    Решение: Убедитесь, что WP-CLI установлен и настроен, либо используйте аналогичный скрипт с запуском через cron и PHP.
  • Ошибка: Товары не удаляются, хотя запрос возвращает ID.
    Решение: Проверьте права пользователя, под которым запускается скрипт, и параметры wp_delete_post. Возможно, лучше использовать принудительное удаление (force_delete=true).
  • Ошибка: Удаляются нужные товары.
    Решение: Добавьте в запрос дополнительную фильтрацию по статусу товара (например, только publish), или добавьте мета-поле для исключения.

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

  • Запускайте массовое удаление в периоды наименьшей нагрузки.
  • Обязательно делайте бэкапы перед массовым удалением.
  • Рассмотрите использование wp_delete_post с параметром force_delete = true, чтобы избежать попадания товаров в корзину.
  • Для больших магазинов разбивайте удаление на партии по 100-200 товаров, чтобы избежать таймаутов.
  • Используйте транзакции в базе, если реализуете удаление напрямую через SQL.

Сравнение подходов для удаления товаров без заказов

МетодПлюсыМинусыПример
SQL-запрос и массовое удаление Быстро, без загрузки WordPress Риск ошибок, сложность в учете связей SELECT + DELETE по ID
WP-CLI команда Использует API WP, безопаснее, легко настраивается Требуется доступ к командной строке wp wc-delete-unused-products --days=90
Плагин с функцией удаления Удобно для пользователей без доступа к серверу Может нагружать сайт при большом количестве товаров Пользовательский плагин с кнопкой "Удалить"
Оптимизация WordPress для быстрой загрузки сайта: практические методы и примеры
05.11.2025
Автоматизация обновлений WordPress с WPengine: настройка и примеры
14.12.2025
Как сделать отложенный запуск cron задач в WordPress
10.02.2026
Как использовать внешние библиотеки в WordPress с примерами
30.11.2025
Как создать динамические шорткоды в WordPress с использованием AJAX
30.01.2026