Диагностика проблемы: почему варианты товаров неактивны, но остаются включенными
В WooCommerce часто возникает ситуация, когда вариации товаров с нулевым остатком и отсутствием продаж продолжают отображаться на сайте, создавая путаницу для покупателей и загромождая интерфейс. Это снижает удобство использования и может негативно влиять на конверсию. Основная причина — отсутствие автоматизации отключения таких вариантов, особенно если их много. Вручную управлять ими неудобно и ошибочно.
Как автоматически отключать варианты товаров с нулевым остатком и без продаж
Что нужно учесть перед реализацией
- Убедитесь, что учет запасов включен для вариаций (Manage stock = true).
- Определитесь с периодом, за который считать продажи (например, 30 дней).
- Резервное копирование базы данных перед внесением изменений.
Пошаговое решение с примером кода
Для автоматического отключения вариантов с нулевым остатком и отсутствием продаж за последние 30 дней добавим кастомную функцию на cron или вызов вручную.
function wc_disable_inactive_variations() {
$args = array(
'post_type' => 'product_variation',
'posts_per_page' => -1,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => '_stock_status',
'value' => 'outofstock'
),
array(
'key' => '_manage_stock',
'value' => 'yes'
)
)
);
$variations = get_posts($args);
$threshold_date = strtotime('-30 days');
foreach ($variations as $variation) {
$variation_id = $variation->ID;
// Получаем количество продаж вариации за последние 30 дней
global $wpdb;
$sales_count = $wpdb->get_var($wpdb->prepare(
"SELECT SUM(oi.meta_value) FROM {$wpdb->prefix}woocommerce_order_items AS oi
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS oim ON oi.order_item_id = oim.order_item_id
LEFT JOIN {$wpdb->prefix}posts AS p ON p.ID = oi.order_id
WHERE oi.order_item_type = 'line_item'
AND oim.meta_key = '_variation_id'
AND oim.meta_value = %d
AND p.post_type = 'shop_order'
AND p.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold')
AND p.post_date >= %s
AND oi.order_item_id = oi.order_item_id
AND EXISTS (
SELECT 1 FROM {$wpdb->prefix}woocommerce_order_itemmeta AS qty_meta
WHERE qty_meta.order_item_id = oi.order_item_id
AND qty_meta.meta_key = '_qty'
)",
$variation_id,
date('Y-m-d H:i:s', $threshold_date)
));
$sales_count = intval($sales_count);
if ($sales_count === 0) {
// Отключаем вариант
wp_update_post(array(
'ID' => $variation_id,
'post_status' => 'draft'
));
}
}
}
// Пример вызова функции вручную или через WP-Cron
// wc_disable_inactive_variations();Как добавить запуск функции по расписанию
Добавьте в functions.php или в плагин следующее для ежедневного запуска:
if (!wp_next_scheduled('wc_disable_inactive_variations_daily')) {
wp_schedule_event(time(), 'daily', 'wc_disable_inactive_variations_daily');
}
add_action('wc_disable_inactive_variations_daily', 'wc_disable_inactive_variations');Проверка результата после внедрения
- Перейдите в раздел «Вариации» нужного товара и убедитесь, что варианты с нулевым остатком и без продаж стали со статусом «Черновик» (draft) и не отображаются на сайте.
- Проверьте логи cron, если используете планировщик, или вызовите функцию вручную и убедитесь в отсутствии ошибок.
- Для теста создайте вариацию с нулевым остатком и без продаж, запустите функцию и проверьте её статус.
Частые ошибки и как их исправить
- Неправильный статус вариации после обновления. Причина: функция использует wp_update_post с неверным статусом. Проверьте, что используете
post_status => 'draft'для скрытия вариации. - Функция не находит вариации. Убедитесь, что в базе вариации имеют статус
publishи метаполя_stock_status = outofstock, а также_manage_stock = yes. - Неверный подсчет продаж. В SQL-запросе учитываются только статусы заказов
wc-completed,wc-processing,wc-on-hold. Измените список при необходимости. - Функция не запускается по расписанию. Проверьте активность WP-Cron, его логи и наличие планировщика задач на сервере.
Практические советы по безопасности и производительности
- Перед массовыми изменениями всегда делайте резервную копию базы.
- Для сайтов с большим количеством вариаций делайте обработку частями (например, по 100 штук за один запуск) чтобы не перегружать сервер.
- Используйте WP-CLI для запуска скриптов вручную или в cron, это надежнее чем WP-Cron на слабых хостингах.
- Добавьте проверку nonce и прав пользователя, если планируете запускать функцию через админку.
- Кэшируйте результаты запроса продаж, если запускаете часто, чтобы снизить нагрузку на базу.
Сравнение способов решения задачи
| Метод | Преимущества | Недостатки |
|---|---|---|
| Ручное отключение вариаций | Простота, не требует кода | Трудозатратно, риск ошибок при большом количестве товаров |
| Плагин для управления запасами | Готовое решение, поддержка | Может быть платным, дополнительные зависимости |
| Кастомный скрипт на PHP (как в статье) | Полный контроль, бесплатное решение, легко адаптировать | Требует навыков разработки, ответственность за тестирование |