Диагностика проблемы: зачем удалять неактивные вариации товаров в WooCommerce
При работе с WooCommerce часто накапливаются вариации товаров, которые перестают быть актуальными — например, товары с нулевым остатком, неактивные по статусу или не продающиеся долгое время. Такие вариации занимают место в базе данных, замедляют работу сайта, усложняют администрирование и могут привести к путанице в заказах.
Если вы замечаете, что в админке WooCommerce много вариаций, которые не продаются и не используются, это сигнал к тому, чтобы автоматизировать их удаление.
Пошаговое решение: как автоматически удалить неактивные вариации без плагинов
1. Определяем критерии неактивности вариаций
Чаще всего неактивные вариации — это те, у которых:
- статус «черновик» или «отменён»;
- отсутствует запас на складе;
- нет заказов за определённый период (например, 6 месяцев);
- отключены для продажи (приватный статус или meta поле «_stock_status» = «outofstock»).
Мы будем ориентироваться на статус поста и наличие запасов.
2. Создаем WP-Cron задачу для регулярного удаления вариаций
Добавьте следующий код в файл functions.php вашей темы или в кастомный плагин:
if (!wp_next_scheduled('wc_delete_inactive_variations')) {
wp_schedule_event(time(), 'daily', 'wc_delete_inactive_variations');
}
add_action('wc_delete_inactive_variations', 'wc_delete_old_inactive_variations');
function wc_delete_old_inactive_variations() {
global $wpdb;
// Получаем ID вариаций с нулевым запасом и статусом 'private' или 'draft'
$query = "
SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm_stock ON (p.ID = pm_stock.post_id AND pm_stock.meta_key = '_stock_status')
WHERE p.post_type = 'product_variation'
AND (p.post_status = 'draft' OR p.post_status = 'private')
AND (pm_stock.meta_value = 'outofstock' OR pm_stock.meta_value IS NULL)
";
$variations = $wpdb->get_col($query);
if (!empty($variations)) {
foreach ($variations as $variation_id) {
wp_delete_post($variation_id, true); // жесткое удаление
}
}
}Код запускает ежедневную задачу, которая удаляет вариации с черновым или приватным статусом и отсутствием запаса на складе.
3. Расширение фильтра: удаление вариаций без заказов за 6 месяцев
Чтобы добавить проверку на отсутствие заказов за последние 6 месяцев, используйте такой подход:
function wc_delete_inactive_variations() {
global $wpdb;
$six_months_ago = date('Y-m-d H:i:s', strtotime('-6 months'));
$query = "
SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm_stock ON (p.ID = pm_stock.post_id AND pm_stock.meta_key = '_stock_status')
LEFT JOIN (
SELECT order_item_meta.meta_value AS variation_id, MAX(posts.post_date) AS last_order_date
FROM {$wpdb->prefix}woocommerce_order_items AS order_items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
INNER JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE order_item_meta.meta_key = '_variation_id'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ('wc-completed', 'wc-processing')
GROUP BY order_item_meta.meta_value
) AS orders ON p.ID = orders.variation_id
WHERE p.post_type = 'product_variation'
AND (p.post_status = 'draft' OR p.post_status = 'private')
AND (pm_stock.meta_value = 'outofstock' OR pm_stock.meta_value IS NULL)
AND (orders.last_order_date IS NULL OR orders.last_order_date < %s)
";
$prepared_query = $wpdb->prepare($query, $six_months_ago);
$variations = $wpdb->get_col($prepared_query);
if (!empty($variations)) {
foreach ($variations as $variation_id) {
wp_delete_post($variation_id, true);
}
}
}Проверка результата после внедрения
- Выполните вручную запуск задачи из админки WP-CLI:
wp cron event run wc_delete_inactive_variations. Если WP-CLI нет, временно вызовите функцию вручную. - Проверьте таблицу
wp_posts— вариации с указанными критериями должны исчезнуть. - В админке WooCommerce откройте список вариаций и убедитесь, что неактивные вариации удалены.
- Отслеживайте логи ошибок и базу данных на предмет удаления нужных записей.
Частые ошибки и как их исправить
- Ошибка в SQL-запросе: Неверный join или опечатки в названиях таблиц приводят к пустым результатам. Проверьте префикс таблиц
$wpdb->prefixи соответствие полей. - Неправильный статус вариаций: Некоторые вариации могут иметь статус
publish, но быть неактивными. Добавьте дополнительные проверки по мета-данным. - Отсутствие прав на удаление: Функция
wp_delete_postтребует прав администратора. Убедитесь, что задача запускается от имени пользователя с нужными правами. - Конфликт с кэшированием: После удаления вариаций очистите кэш сайта и браузера, чтобы изменения отобразились.
Практические советы по безопасности и производительности
- Резервное копирование базы данных: Перед внедрением автоматического удаления сделайте полную резервную копию базы данных.
- Запуск WP-Cron: По умолчанию WP-Cron запускается при посещении сайта, что может привести к задержкам. Лучше настроить системный cron на сервере для запуска
wp cron event run --due-nowкаждые 5-10 минут. - Логирование: Добавьте логирование удалённых вариаций в файл для аудита и отката при ошибках.
- Оптимизация запросов: При большом каталоге товаров разбивайте удаление на партии, чтобы избежать превышения лимита памяти или таймаута.
Сравнение вариантов решения
| Метод | Плюсы | Минусы | Пример кода/плагина |
|---|---|---|---|
| Код с WP-Cron | Полный контроль, отсутствие зависимостей, можно настроить под свои критерии | Требует навыков программирования, возможны ошибки в SQL | Приведён в статье |
| Плагины для очистки WooCommerce | Простота использования, готовые интерфейсы | Зависимость от сторонних решений, не всегда гибко | WP-Optimize, Advanced Database Cleaner |
| Ручное удаление через админку | Простота, без риска автоматических ошибок | Затратно по времени, неэффективно при большом количестве вариаций | Стандартный интерфейс WooCommerce |