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

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

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

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

Под непроданными товарами в рамках этой задачи считаются товары, у которых нет ни одного завершенного заказа за определенный период (например, 90 дней). Для этого нам нужно:

  • Определить дату последней продажи товара.
  • Сравнить с текущей датой.
  • Выбрать товары без заказов или с последними продажами старше порога.

Пошаговое решение: автоматическое удаление товаров через WP-Cron

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

В этом примере удаляются товары без продаж за последние 90 дней.

function wc_delete_unsold_products() {
    $days = 90;
    $cutoff = strtotime("-" . $days . " days");

    // Получаем ID всех товаров
    $args = [
        'post_type'      => 'product',
        'posts_per_page' => -1,
        'fields'         => 'ids',
        'post_status'    => 'publish',
    ];
    $product_ids = get_posts($args);
    
    foreach ($product_ids as $product_id) {
        // Получаем даты завершенных заказов для товара
        global $wpdb;
        $query = $wpdb->prepare(
            "SELECT MAX(p.post_date) FROM {$wpdb->prefix}posts p
            INNER JOIN {$wpdb->prefix}woocommerce_order_items oi ON p.ID = oi.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
            WHERE p.post_type = 'shop_order'
            AND p.post_status IN ('wc-completed', 'wc-processing')
            AND oim.meta_key = '_product_id'
            AND oim.meta_value = %d",
            $product_id
        );
        $last_order_date = $wpdb->get_var($query);

        // Если нет продаж или последняя продажа старше cutoff
        if (empty($last_order_date) || strtotime($last_order_date) < $cutoff) {
            // Удаляем товар без перемещения в корзину
            wp_delete_post($product_id, true);
        }
    }
}

2. Регистрируем WP-Cron задачу

Добавляем событие в расписание, чтобы функция запускалась ежедневно.

function wc_schedule_delete_unsold_products() {
    if (!wp_next_scheduled('wc_delete_unsold_products_daily')) {
        wp_schedule_event(time(), 'daily', 'wc_delete_unsold_products_daily');
    }
}
add_action('wp', 'wc_schedule_delete_unsold_products');

add_action('wc_delete_unsold_products_daily', 'wc_delete_unsold_products');

3. Отключение задачи (при необходимости)

function wc_unschedule_delete_unsold_products() {
    $timestamp = wp_next_scheduled('wc_delete_unsold_products_daily');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'wc_delete_unsold_products_daily');
    }
}

Как проверить, что решение работает

  • Включите WP_DEBUG и просмотрите логи ошибок (если добавите логирование в функцию удаления).
  • Проверьте список товаров в админке WooCommerce — непроданные товары старше 90 дней должны исчезать после запуска cron.
  • Ручной запуск функции через админский плагин WP Crontrol (https://ru.wordpress.org/plugins/wp-crontrol/) позволит проверить без ожидания.

Частые ошибки и способы их устранения

  • WP-Cron не работает из-за отключенного cron в сервере. Проверьте, что WP-Cron активен или настройте системный cron для вызова wp-cron.php.
  • Удаление не происходит из-за кеширования. Очистите кеш сайта и браузера, проверьте работу на чистом режиме.
  • SQL-запрос неверно возвращает даты. Проверьте префикс таблиц и наличие заказов с нужным статусом.
  • Товары не удаляются, так как функция не вызывается. Убедитесь, что хук cron и функция зарегистрированы правильно.

Практические советы по оптимизации и безопасности

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

Сравнение подходов: плагин vs код vs WP-Cron

ПодходПреимуществаНедостатки
Плагин (например, WP Bulk Delete)Простота настройки, GUI, регулярные обновленияМожет нагружать сайт, не всегда гибко
Код с WP-CronГибкость, точечные задачи, минимальные зависимостиТребует навыков, нужно следить за cron
Ручное удалениеКонтроль над каждым товаромТрудозатратно, риск ошибок
Как использовать REST API WordPress для автоматизации задач
15.12.2025
WooCommerce: как автоматически удалять непроданные товары через WP-Cron
01.06.2026
Оптимизация базы данных WordPress: используем плагины и пишем свой код
21.11.2025
Как массово изменить или удалить атрибуты alt и title в изображениях WordPress
06.12.2025
Как автоматически изменять заголовки постов WordPress по шаблону
10.03.2026