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

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

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

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

Для реализации удаления необходимо аккуратно выявить товары, которые не имеют связанных заказов. В WooCommerce связь товаров и заказов хранится в таблицах базы данных: wp_posts для товаров (post_type = 'product') и wp_posts для заказов (post_type = 'shop_order'). Связь между заказом и товаром хранится в wp_woocommerce_order_items и wp_woocommerce_order_itemmeta.

Проверить, есть ли заказы с конкретным ID товара, можно через SQL-запрос, но в коде WordPress проще использовать WC API и WP_Query.

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

1. Создаем WP-Cron задачу для еженедельной проверки

if (!wp_next_scheduled('wptem_delete_unsold_products')) {
    wp_schedule_event(time(), 'weekly', 'wptem_delete_unsold_products');
}

2. Функция для удаления товаров без заказов за X дней

function wptem_delete_unsold_products_callback() {
    $days_threshold = 90; // Количество дней с момента публикации
    $date_threshold = date('Y-m-d H:i:s', strtotime('-' . $days_threshold . ' days'));

    // Получаем товары, опубликованные до пороговой даты
    $args = [
        'post_type'      => 'product',
        'posts_per_page' => -1,
        'date_query'     => [
            [
                'before' => $date_threshold,
                'inclusive' => true,
            ],
        ],
        'post_status'    => 'publish',
        'fields'         => 'ids',
    ];
    $products = get_posts($args);

    foreach ($products as $product_id) {
        // Проверяем есть ли заказы с этим товаром
        if (!wptem_product_has_orders($product_id)) {
            wp_delete_post($product_id, true); // Полное удаление
        }
    }
}
add_action('wptem_delete_unsold_products', 'wptem_delete_unsold_products_callback');

function wptem_product_has_orders($product_id) {
    global $wpdb;

    $query = $wpdb->prepare(
        "SELECT COUNT(DISTINCT order_items.order_id) FROM {$wpdb->prefix}woocommerce_order_items AS order_items
        
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS itemmeta ON order_items.order_item_id = itemmeta.order_item_id
        
        INNER JOIN {$wpdb->prefix}posts AS posts ON posts.ID = order_items.order_id
        
        WHERE order_items.order_item_type = 'line_item'
        
        AND itemmeta.meta_key = '_product_id'
        
        AND itemmeta.meta_value = %d
        
        AND posts.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold')",
        $product_id
    );

    $count = $wpdb->get_var($query);
    return $count > 0;
}

3. Очистка WP-Cron при деактивации плагина/темы

function wptem_deactivate_cleanup() {
    $timestamp = wp_next_scheduled('wptem_delete_unsold_products');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'wptem_delete_unsold_products');
    }
}
register_deactivation_hook(__FILE__, 'wptem_deactivate_cleanup');

Как проверить, что удаление сработало

  • В админке WooCommerce сравните количество товаров до и после запуска крона.
  • Запустите функцию вручную (через WP-CLI или временно добавьте вызов wptem_delete_unsold_products_callback(); в functions.php) и проверьте логи ошибок.
  • Проверьте, что удалены только товары без заказов, опубликованные более 90 дней назад.

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

  • Удаляются товары с заказами: проверьте логику функции wptem_product_has_orders() и правильность статусов заказов в SQL-запросе.
  • Крон не срабатывает: убедитесь, что WP-Cron включен и посещения сайта есть. Для теста используйте WP-CLI: wp cron event run wptem_delete_unsold_products.
  • Превышение лимитов памяти или таймауты: разбейте удаление на партии по 50-100 товаров за запуск, добавив параметр posts_per_page и пагинацию.

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

  • Запускайте удаление товаров только по расписанию, а не на каждом запросе.
  • Делайте резервные копии базы перед автоматическим удалением.
  • Добавьте логирование удалений в отдельный файл или таблицу для аудита.
  • Для больших магазинов с тысячами товаров используйте пагинацию и оптимизируйте SQL-запросы.

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

МетодПлюсыМинусы
WP-Cron с кастомным кодомГибкость, кастомизация, без сторонних плагиновТребует знаний, настройка cron, возможны таймауты при большом объеме
Плагины очистки WooCommerceПростота настройки, готовые решенияМогут быть избыточными, нагрузка, нет тонкой настройки
Ручное удаление через SQL или админкуКонтроль и точечное удалениеРиск ошибок, неавтоматизировано, трудозатратно
Как создать автоматические отзывы с помощью WPRemark в WordPress
16.04.2026
Как динамически изменять заголовки страниц в WordPress
18.12.2025
Как добавить динамические фильтры в WordPress
11.04.2026
Как создать свой плагин в WordPress: практическое руководство
28.11.2025
Как использовать REST API WordPress для создания нестандартных запросов
30.12.2025