WooCommerce: как автоматизировать удаление старого товара и отсутствующих вариантов

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

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

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

Сценарии для удаления:

  • Товары со статусом «Черновик» или «Ожидает проверки» старше N дней.
  • Товары, у которых нет активных вариаций или все вариации имеют статус «нет в наличии».
  • Товары, не продававшиеся или не обновлявшиеся в течение длительного времени (например, 6 месяцев).

Пример SQL-запроса для поиска товаров без вариаций

SELECT p.ID, p.post_title FROM wp_posts p LEFT JOIN wp_posts v ON v.post_parent = p.ID AND v.post_type = 'product_variation' WHERE p.post_type = 'product' AND v.ID IS NULL AND p.post_status = 'publish';

Этот запрос вернет опубликованные товары без вариаций.

Пошаговое решение: автоматизация удаления через WP-Cron и пользовательскую функцию

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

function wpmonitor_delete_old_and_missing_products() {
    $days_threshold = 180; // 6 месяцев
    $date_threshold = date('Y-m-d H:i:s', strtotime('-' . $days_threshold . ' days'));

    // 1. Получаем товары, не обновлявшиеся более 6 месяцев
    $args = [
        'post_type' => 'product',
        'post_status' => 'publish',
        'date_query' => [
            'column' => 'post_modified',
            'before' => $date_threshold,
        ],
        'fields' => 'ids',
        'posts_per_page' => -1,
    ];
    $old_products = get_posts($args);

    foreach ($old_products as $product_id) {
        $product = wc_get_product($product_id);

        if (!$product) continue;

        // Проверяем наличие вариаций
        if ($product->is_type('variable')) {
            $variations = $product->get_children();

            // Проверяем, есть ли вариации в наличии
            $has_available_variation = false;
            foreach ($variations as $variation_id) {
                $variation = wc_get_product($variation_id);
                if ($variation && $variation->is_in_stock()) {
                    $has_available_variation = true;
                    break;
                }
            }

            // Если нет доступных вариаций — удаляем товар
            if (!$has_available_variation) {
                wp_delete_post($product_id, true);
            }
        } else {
            // Для простых товаров проверяем наличие
            if (!$product->is_in_stock()) {
                wp_delete_post($product_id, true);
            }
        }
    }

    // 2. Удаляем товары без вариаций вообще
    $args_no_variations = [
        'post_type' => 'product',
        'post_status' => 'publish',
        'fields' => 'ids',
        'posts_per_page' => -1,
        'meta_query' => [],
    ];
    $products = get_posts($args_no_variations);

    foreach ($products as $p_id) {
        $variations = wc_get_product($p_id)->get_children();
        if (empty($variations)) {
            wp_delete_post($p_id, true);
        }
    }
}

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

add_action('wpmonitor_delete_old_products_hook', 'wpmonitor_delete_old_and_missing_products');

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

3. Добавляем отмену задачи при деактивации плагина или темы

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

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

  • Проверьте наличие товаров, которые должны были удалиться (старше 6 месяцев и отсутствующие варианты).
  • Посмотрите лог событий (можно добавить логирование в функцию удаления с помощью error_log или плагина для логов).
  • Убедитесь, что удаление происходит корректно без удаления нужных товаров.

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

  • Удаляются нужные товары. Проверьте логику условий — возможно, стоит увеличить порог времени или добавить дополнительные проверки.
  • WP-Cron не запускается. Убедитесь, что на сайте есть посещения (WP-Cron запускается по ним) или настройте системный cron для вызова wp-cron.php.
  • Функция не удаляет вариации. Проверьте, что используете правильные методы WooCommerce для получения вариаций и их статусов.

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

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

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

МетодПлюсыМинусыКогда применять
Ручное удаление через админкуПросто, без кодаТрудозатратно, риск ошибокНебольшие магазины, редко
Пользовательская функция с WP-Cron (как в статье)Автоматизация, гибкие условияНужны знания PHP, потенциальные ошибкиСредние и крупные магазины
Плагины очистки и оптимизации (напр. Clearfy Pro)Удобно, поддержка, доп. функцииПлатные, ограниченная кастомизацияЕсли нужны комплексные решения
WooCommerce: как исправить проблему с неотображением цены товара после обновления
31.05.2026
WooCommerce: не отображается название атрибута товара после обновления — как исправить
23.05.2026
Как отключить автоматическое удаление старых записей через WP-Cron в WordPress
24.03.2026
Как мониторить использование памяти в WordPress: практические методы и примеры
13.02.2026
WooCommerce: как автоматически очищать корзину после успешной оплаты
20.05.2026