Диагностика проблемы: почему неактивные вариации мешают
В WooCommerce вариации товаров могут накапливаться, даже если они больше не актуальны — например, устаревшие варианты с нулевым запасом или временно отключённые. Это приводит к замедлению сайта, увеличению размера базы данных и усложнению управления каталогом.
Чтобы проверить наличие неактивных вариаций, выполните SQL-запрос в базе через phpMyAdmin:
SELECT ID, post_title, post_status
FROM wp_posts
WHERE post_type = 'product_variation' AND post_status != 'publish';
Если таких записей много — пора их чистить.
Пошаговое решение: удаляем неактивные вариации через PHP
Рассмотрим код, который удалит все вариации с любым статусом, кроме publish. Добавьте этот код в файл functions.php вашей темы или создайте плагин для кастомных функций.
function delete_inactive_product_variations() {
$args = [
'post_type' => 'product_variation',
'post_status' => ['draft', 'pending', 'private', 'trash', 'auto-draft'],
'posts_per_page' => -1,
'fields' => 'ids',
];
$variations = get_posts($args);
if (empty($variations)) {
error_log('No inactive variations found to delete.');
return;
}
foreach ($variations as $variation_id) {
wp_delete_post($variation_id, true); // true - удалить без возможности восстановления
}
error_log('Deleted ' . count($variations) . ' inactive variations.');
}
// Запускаем очистку один раз при загрузке админки
add_action('admin_init', function() {
if (current_user_can('manage_woocommerce') && isset($_GET['delete_inactive_variations'])) {
delete_inactive_product_variations();
wp_redirect(remove_query_arg('delete_inactive_variations'));
exit;
}
});
Для запуска очистки зайдите в админку WordPress и добавьте к URL параметр ?delete_inactive_variations=1, например, https://example.com/wp-admin/?delete_inactive_variations=1.
Альтернативный фильтр по запасам
Можно дополнительно удалять вариации с нулевым запасом (stock_quantity = 0), если они не нужны:
function delete_variations_with_zero_stock() {
global $wpdb;
$variation_ids = $wpdb->get_col("SELECT p.ID FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = 'product_variation'
AND pm.meta_key = '_stock'
AND pm.meta_value = '0'");
foreach ($variation_ids as $variation_id) {
wp_delete_post($variation_id, true);
}
}
// Используйте осторожно, добавив вызов по аналогии с предыдущим примером.
Проверка результата после внедрения
- Повторите SQL-запрос из раздела диагностики — неактивных вариаций должно стать значительно меньше или они исчезнут.
- Проверьте в админке WooCommerce — вариации с статусом «Черновик» и другие должны исчезнуть.
- Просмотрите логи ошибок (error_log) для подтверждения успешного удаления.
Частые ошибки и как их исправить
- Нет эффекта после запуска кода: Проверьте, что вызов функции происходит и вы используете правильный URL с параметром
?delete_inactive_variations=1. - Удаляются нужные вариации: Убедитесь, что фильтр по статусу или запасу корректен. Лучше сначала вывести ID для проверки, вместо удаления, например, через
error_log(print_r($variations, true));. - Проблемы с правами: Убедитесь, что текущий пользователь имеет права
manage_woocommerce. - Ошибки базы данных: Проверьте префикс таблиц и корректность запросов, особенно если префикс отличается от
wp_.
Практические советы по безопасности и производительности
- Перед массовым удалением сделайте резервную копию базы данных.
- Запускайте удаление только вручную или по расписанию с контролем — чтобы избежать случайных потерь.
- Если вариаций очень много, разбивайте удаление на партии, чтобы избежать таймаута PHP.
- Для регулярной очистки используйте WP-Cron с ограничением по времени и объему.
Сравнение вариантов удаления неактивных вариаций
| Метод | Преимущества | Недостатки | Компромисс |
|---|---|---|---|
| Ручное удаление через админку WooCommerce | Простота, визуальный контроль | Много времени при большом количестве | Использовать для единичных случаев |
| SQL-запросы напрямую в базе | Быстро, без нагрузки на PHP | Риск ошибочного удаления, нет логов | Использовать с осторожностью и бэкапом |
| PHP-скрипты с wp_delete_post() | Безопасно, учитывает хуки, можно логировать | Может быть медленнее, требует навыков | Оптимально для регулярной и контролируемой очистки |