Диагностика проблемы с вариациями товаров в WooCommerce
Если ваш магазин на WooCommerce содержит большое количество вариаций товаров, некоторые из них могут со временем стать неактуальными или неиспользуемыми — например, из-за отсутствия продаж, отсутствия запасов или удаления родительского атрибута. Это приводит к увеличению нагрузки на базу данных, замедлению работы сайта и сложности в администрировании.
Проверить наличие неиспользуемых вариаций можно через SQL-запрос к базе данных или с помощью кода, который анализирует метаданные товаров.
Пример SQL-запроса для выявления вариаций без заказов и с нулевым запасом:
SELECT p.ID, p.post_title FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_name = p.post_title
LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID AND pm.meta_key = '_stock'
WHERE p.post_type = 'product_variation'
GROUP BY p.ID
HAVING COUNT(oi.order_item_id) = 0 AND (pm.meta_value IS NULL OR pm.meta_value = '0');Этот запрос покажет вариации, которые не были куплены и не имеют запасов. Такие вариации чаще всего можно удалить.
Пошаговое решение: автоматическое удаление неиспользуемых вариаций
Чтобы автоматически удалять неиспользуемые вариации, можно написать функцию, которая:
- Получает все вариации товаров
- Проверяет, есть ли у вариации продажи (через связку с заказами)
- Проверяет наличие запасов
- Удаляет вариации, которые не продаются и не имеют запасов
Пример кода для размещения в functions.php темы или в отдельном плагине:
function wc_remove_unused_variations() {
$args = [
'post_type' => 'product_variation',
'posts_per_page' => -1,
'fields' => 'ids',
];
$variations = get_posts($args);
foreach ($variations as $variation_id) {
// Проверяем продажи вариации
$orders_with_variation = new WP_Query([
'post_type' => 'shop_order',
'post_status' => ['wc-completed', 'wc-processing'],
'posts_per_page' => 1,
'meta_query' => [[
'key' => '_product_id',
'value' => $variation_id,
'compare' => '=',
]],
]);
// Проверяем наличие запаса
$stock = get_post_meta($variation_id, '_stock', true);
if (!$orders_with_variation->have_posts() && (empty($stock) || $stock == '0')) {
wp_delete_post($variation_id, true);
}
}
}
// Добавьте вызов этой функции по крону или вручную
// wc_remove_unused_variations();Обратите внимание, что запрос к заказам в WP_Query по мета-данным вариации требует доработки под структуру WooCommerce, поэтому для точного определения продаж лучше использовать прямые запросы к таблицам woocommerce_order_items и woocommerce_order_itemmeta.
Оптимизированный пример запроса к заказам и удаление вариаций
function wc_remove_unused_variations_optimized() {
global $wpdb;
$variation_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'product_variation'");
foreach ($variation_ids as $variation_id) {
// Проверяем продажи вариации
$order_count = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_order_items oi
JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
JOIN {$wpdb->posts} p ON p.ID = oi.order_id
WHERE oim.meta_key = '_variation_id' AND oim.meta_value = %d
AND p.post_status IN ('wc-completed', 'wc-processing')",
$variation_id
));
$stock = get_post_meta($variation_id, '_stock', true);
if ($order_count == 0 && (empty($stock) || $stock == '0')) {
wp_delete_post($variation_id, true);
}
}
}
// Для безопасного запуска рекомендуется привязать к WP-Cron или запускать вручную
// wc_remove_unused_variations_optimized();Как проверить результат после удаления вариаций
- Просмотрите список вариаций в административной панели WooCommerce — неиспользуемые должны исчезнуть.
- Запустите SQL-запрос из блока диагностики повторно — количество неиспользуемых вариаций должно быть равно нулю.
- Проверьте работу фронтенда — страницы товаров должны отображаться корректно без ошибок 404 на вариациях.
- Проверьте логи ошибок сервера на предмет сообщений, связанных с удалёнными вариациями.
Частые ошибки при автоматическом удалении вариаций и их исправление
- Удаление вариаций, которые ещё используются в заказах. Причина: неправильный запрос к заказам. Решение: использовать точный SQL с JOIN таблиц
woocommerce_order_itemsиwoocommerce_order_itemmetaпо ключу_variation_id. - Удаление вариаций с запасом. Причина: некорректное получение значения
_stock, например, кэширование или нестандартное хранение. Решение: использовать функциюwc_get_product($variation_id)->get_stock_quantity(). - Высокая нагрузка при запуске функции на больших магазинах. Решение: разбивать обработку на части, например, по 100 вариаций за раз, использовать WP-Cron для регулярного запуска.
Практические советы по безопасности и производительности
- Перед запуском автоматического удаления сделайте резервную копию базы данных.
- Тестируйте скрипт на копии сайта или staging-среде.
- Используйте транзакции при работе с базой в кастомных запросах для предотвращения частичного удаления.
- Для больших магазинов запускайте удаление в рамках WP-Cron с лимитом на количество обработанных вариаций за один запуск.
- Добавьте логирование удалённых вариаций в отдельный файл для аудита.
Сравнение методов удаления вариаций
| Метод | Плюсы | Минусы | Рекомендуемая сфера |
|---|---|---|---|
| Ручное удаление через админку WooCommerce | Простота, безопасность | Долгое при большом количестве вариаций | Малые магазины |
| Код на PHP с WP_Query | Гибкость, автоматизация | Сложный поиск заказов, нагрузка | Средние магазины |
| Код на PHP с прямыми SQL-запросами | Быстрота, точность | Риск ошибок, требуется опыт работы с БД | Крупные магазины с админом-специалистом |