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

Диагностика проблемы с неактивными вариантами товаров

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

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

  • Отсутствие остатков на складе (_stock = 0 или меньше)
  • Статус варианта — «черновик» или «приватный» (если используется)
  • Вариант не обновлялся или не покупался в течение длительного времени — дополнительный критерий, если есть кастомные метаполя с датами

Чаще всего достаточно ограничиться проверкой наличия на складе.

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

Реализуем wp-cron задачу, которая раз в сутки будет находить и удалять вариации с нулевым запасом.

1. Регистрация wp-cron события

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

2. Функция удаления неактивных вариаций

add_action('wpb_delete_inactive_variations', function() {
    $args = [
        'post_type'      => 'product_variation',
        'posts_per_page' => -1,
        'meta_query'     => [
            [
                'key'     => '_stock',
                'value'   => 0,
                'compare' => '<=',
                'type'    => 'NUMERIC'
            ]
        ],
        'fields'         => 'ids',
        'post_status'    => 'publish'
    ];

    $query = new WP_Query($args);
    if ($query->have_posts()) {
        foreach ($query->posts as $variation_id) {
            wp_delete_post($variation_id, true); // Полное удаление из базы
        }
    }
});

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

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

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

Для проверки работы решения:

  1. Создайте несколько вариаций товаров с запасом 0 и выше.
  2. Запустите задачу вручную, вызвав хук через WP-CLI:
    wp cron event run wpb_delete_inactive_variations
  3. Проверьте, что вариации с запасом 0 удалились из базы (в админке или через запрос к базе SELECT * FROM wp_posts WHERE post_type = 'product_variation';).
  4. Убедитесь, что остальные вариации остались без изменений.

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

  • Задача не запускается: убедитесь, что WP-Cron включен (константа DISABLE_WP_CRON не установлена в true), или запустите cron вручную.
  • Вариации не удаляются: проверьте правильность мета ключа _stock и типы данных, попробуйте вывести var_dump($query->posts) для диагностики.
  • Удаление не полное: используйте wp_delete_post($id, true) с параметром true для полного удаления без помещения в корзину.
  • Конфликты с плагинами кеширования: отключите кеширование на время теста, чтобы видеть актуальные результаты.

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

  • Для крупных магазинов с тысячами вариаций разбивайте удаление на пачки по 50-100, чтобы избежать превышения лимита памяти и времени выполнения. Пример кода с пагинацией:
function wpb_delete_inactive_variations_batch($paged = 1) {
    $args = [
        'post_type'      => 'product_variation',
        'posts_per_page' => 100,
        'paged'          => $paged,
        'meta_query'     => [
            [
                'key'     => '_stock',
                'value'   => 0,
                'compare' => '<=',
                'type'    => 'NUMERIC'
            ]
        ],
        'fields'         => 'ids',
        'post_status'    => 'publish'
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        foreach ($query->posts as $variation_id) {
            wp_delete_post($variation_id, true);
        }
        if ($paged < $query->max_num_pages) {
            wpb_delete_inactive_variations_batch($paged + 1);
        }
    }
}

add_action('wpb_delete_inactive_variations', function() {
    wpb_delete_inactive_variations_batch();
});
  • Регулярно создавайте резервные копии базы перед автоматическими удалениями.
  • Логируйте удалённые ID вариаций в файл для аудита:
function wpb_log_deleted_variations($variation_id) {
    $log_file = WP_CONTENT_DIR . '/deleted_variations.log';
    file_put_contents($log_file, date('Y-m-d H:i:s') . " - Удален вариант: {$variation_id}\n", FILE_APPEND);
}

add_action('wp_delete_post', function($postid) {
    $post = get_post($postid);
    if ($post && $post->post_type === 'product_variation') {
        wpb_log_deleted_variations($postid);
    }
});

Сравнение вариантов автоматического удаления

МетодПлюсыМинусы
Плагин очистки (например, WP Cleaner)Простота использования, интерфейсМожет быть тяжеловесным, не всегда гибкий
Ручное удаление через админкуПолный контрольТрудоемко, не подходит для больших магазинов
Автоматизация через WP-Cron и кастомный кодГибкость, интеграция в бизнес-процессыТребует навыков разработки и тестирования
Как отключить REST API в WordPress без потери функциональности
01.04.2026
Автоматическое удаление неактивных вариантов товаров WooCommerce по расписанию без плагинов
24.06.2026
Как добавить уникальное пользовательское поле в регистрацию WordPress
23.01.2026
Как создать собственный тип записи (Custom Post Type) в WordPress с примером кода
16.04.2026
Как добавить уникальные метаполя для продукта WooCommerce с примером кода
24.02.2026