Сценарий знакомый: у товара есть вариации, склад ведётся по каждой из них, но на карточке покупатель видит только общий статус вроде «В наличии» или «Нет в наличии». Для магазина это неудобно: человек выбирает цвет или размер, а понять, какая именно вариация доступна, можно только после клика. В WooCommerce это решается либо настройкой шаблона, либо небольшим кодом в теме/мини-плагине.
Ниже — практический вариант без выдуманных хуков и без тяжёлых расширений. Сначала разберём, где именно ломается логика отображения, потом добавим вывод остатка для выбранной вариации и проверим, что всё работает на фронтенде и в админке.
Когда проблема действительно в WooCommerce, а не в теме
Прежде чем править код, стоит понять, что именно вы хотите показать. WooCommerce умеет хранить наличие на уровне вариации, но тема может просто не выводить этот блок, либо скрывать его CSS-ом. Ещё один частый случай — остатки отключены в настройках товара, и тогда у вариаций нет данных для вывода.
Что проверить в первую очередь
- У товара включён тип
variable product. - Для каждой вариации заполнен флаг
Управлять запасами?, если вы ведёте склад поштучно. - В WooCommerce → Настройки → Товары → Запасы не отключён общий показ наличия.
- Тема не переопределяет шаблон
single-product/add-to-cart/variable.phpслишком агрессивно. - На странице товара нет JS-ошибок, которые ломают обновление блока вариации.
Если в админке остатки у вариаций есть, а на странице товара их не видно, проблема почти всегда на стороне шаблона или фронтенд-логики.
Диагностика: где WooCommerce теряет данные о наличии
Самый быстрый способ проверить, отдаёт ли WooCommerce данные по вариации, — посмотреть объект вариации в JavaScript. На странице товара WooCommerce подставляет данные в форму выбора вариаций, и именно оттуда можно понять, есть ли у конкретной вариации остаток, статус и текст для вывода.
jQuery(function($) {
$('.variations_form').on('found_variation', function(event, variation) {
console.log('Variation ID:', variation.variation_id);
console.log('In stock:', variation.is_in_stock);
console.log('Stock status:', variation.stock_status);
console.log('Availability text:', variation.availability_html);
});
});Если в консоли availability_html пустой, это не всегда ошибка. Иногда тема просто не выводит этот фрагмент. Но если is_in_stock всегда false при наличии товара на складе, тогда уже стоит смотреть настройки конкретной вариации и синхронизацию остатков.
Пошаговое решение: вывод наличия выбранной вариации на карточке товара
Надёжный способ — добавить отдельный контейнер под селекторами вариаций и заполнять его через стандартное событие WooCommerce found_variation. Так вы не ломаете шаблон и не зависите от того, как тема рисует кнопку покупки.
Шаг 1. Добавляем контейнер для статуса
Вставьте код в functions.php дочерней темы или в собственный мини-плагин. Хук woocommerce_single_variation сработает в блоке выбора вариации и позволит вывести дополнительный HTML рядом с кнопкой покупки.
add_action('woocommerce_single_variation', function () {
echo '<div class="variation-stock-status" aria-live="polite" style="margin-top:10px;"></div>';
}, 25);Шаг 2. Подключаем скрипт и передаём текстовые шаблоны
Дальше нужен небольшой скрипт, который будет подставлять текст при выборе вариации. Здесь лучше не хардкодить строки в JS, а передать их через wp_localize_script.
add_action('wp_enqueue_scripts', function () {
if (!is_product()) {
return;
}
wp_enqueue_script(
'variation-stock-status',
get_stylesheet_directory_uri() . '/js/variation-stock-status.js',
array('jquery', 'wc-add-to-cart-variation'),
'1.0.0',
true
);
wp_localize_script('variation-stock-status', 'VariationStockStatus', array(
'inStock' => 'В наличии',
'outOfStock' => 'Нет в наличии',
'backorder' => 'Доступно под заказ',
));
});Шаг 3. Пишем JS для обновления статуса
Файл /js/variation-stock-status.js должен слушать выбор вариации и обновлять текст в контейнере. Если вариация сброшена, блок лучше очищать, чтобы не показывать старый статус.
jQuery(function($) {
var $form = $('.variations_form');
var $status = $('.variation-stock-status');
if (!$form.length || !$status.length) {
return;
}
$form.on('found_variation', function(event, variation) {
var text = '';
if (variation.is_in_stock) {
text = VariationStockStatus.inStock;
} else if (variation.backorders_allowed) {
text = VariationStockStatus.backorder;
} else {
text = VariationStockStatus.outOfStock;
}
$status.text(text);
});
$form.on('reset_data', function() {
$status.empty();
});
});Этот вариант не подменяет стандартную логику WooCommerce, а только показывает покупателю понятный статус выбранной вариации.
Если нужен не просто текст, а HTML-блок с цветом и иконкой
Иногда достаточно не строки, а компактного бейджа. Тогда можно выводить разные CSS-классы в зависимости от статуса. Это удобнее для магазинов, где важно визуально отделять «в наличии», «под заказ» и «нет в наличии».
jQuery(function($) {
var $form = $('.variations_form');
var $status = $('.variation-stock-status');
$form.on('found_variation', function(event, variation) {
var className = 'stock-unknown';
var text = '';
if (variation.is_in_stock) {
className = 'stock-in';
text = 'В наличии';
} else if (variation.backorders_allowed) {
className = 'stock-backorder';
text = 'Под заказ';
} else {
className = 'stock-out';
text = 'Нет в наличии';
}
$status
.attr('class', 'variation-stock-status ' + className)
.text(text);
});
});А стили можно добавить в файл темы:
.variation-stock-status {
font-size: 14px;
line-height: 1.4;
margin-top: 10px;
}
.variation-stock-status.stock-in {
color: #1e7e34;
}
.variation-stock-status.stock-backorder {
color: #8a6d3b;
}
.variation-stock-status.stock-out {
color: #c62828;
}Сравнение подходов: плагин, код, правка шаблона
| Подход | Что даёт | Минус |
|---|---|---|
| Плагин | Быстрый старт без разработки | Лишняя зависимость и риск конфликтов |
| Код в дочерней теме | Контроль над выводом и логикой | Нужно следить за обновлениями темы |
| Переопределение шаблона WooCommerce | Максимально точная верстка | Сложнее поддерживать после обновлений |
Если задача только в том, чтобы показать статус выбранной вариации, код в дочерней теме обычно быстрее и безопаснее, чем переписывание шаблона целиком.
Проверка результата после внедрения
После добавления кода проверьте не только визуальный вывод, но и данные, которые реально приходят из WooCommerce. Иначе можно получить красивый текст на экране, который не соответствует складу.
- Откройте карточку товара с несколькими вариациями.
- Выберите вариацию с остатком и убедитесь, что статус меняется на
В наличии. - Выберите вариацию без остатка и проверьте текст
Нет в наличии. - Сбросьте выбор и убедитесь, что блок очищается.
- Проверьте страницу в мобильной версии: блок не должен ломать кнопку покупки и отступы.
Если используете кэширование страницы товара, очистите кэш после правок. Для динамического блока это особенно важно: старый HTML может остаться в кэше, даже если JS уже обновлён.
Частые ошибки и как их исправить
Статус не меняется при выборе вариации
Обычно причина в том, что скрипт подключён без зависимости wc-add-to-cart-variation или селектор .variations_form не совпадает с разметкой темы. Сначала проверьте консоль браузера и убедитесь, что событие found_variation вообще срабатывает.
Показывается старый остаток после смены вариации
Это бывает, если обработчик не очищает блок на событии reset_data. Добавьте сброс текста, иначе пользователь увидит статус предыдущего выбора.
WooCommerce пишет «В наличии», хотя на складе ноль
Чаще всего у вариации не включено управление запасом, либо остаток ведётся на уровне родительского товара, а не конкретной вариации. Проверьте настройки каждой вариации отдельно.
Статус есть в HTML, но его не видно
Тогда проблема в стилях темы: блок может быть скрыт display:none, перекрыт соседним элементом или иметь цвет, совпадающий с фоном. Это уже не WooCommerce, а CSS-конфликт.
Безопасность и производительность: что не стоит делать
Не вставляйте такой код в основной файл темы, если тема обновляется отдельно. Для рабочих магазинов лучше использовать дочернюю тему или небольшой mu-plugin, чтобы не потерять правки после обновления.
Не грузите отдельный скрипт на всех страницах сайта. Здесь он нужен только на карточке товара, поэтому проверка is_product() оправдана и снижает лишние запросы.
Если у вас большой каталог и остатки часто меняются, не пытайтесь вычислять статус через тяжёлые AJAX-запросы на каждый клик. WooCommerce уже отдаёт нужные данные в объекте вариации, и этого обычно достаточно.
Если задача шире и вам нужно не только показывать наличие, но и менять текст, бейджи или блоки внимания на карточке товара, удобно держать такие правки в одном месте. Для редакционных блоков и заметных уведомлений можно посмотреть и готовые решения вроде WPRemark, если они органично вписываются в дизайн магазина: WPRemark.
В итоге рабочая схема простая: проверяем, что WooCommerce реально отдаёт данные по вариации, добавляем отдельный контейнер под статус, обновляем его через стандартные события и тестируем на нескольких сценариях склада. Это проще, чем переписывать шаблон целиком, и легче поддерживается при обновлениях.