Сценарий типичный: в магазине есть категории, где нужно показывать только товары без остатка, предзаказы или позиции под заказ. При этом в остальных разделах товары в наличии должны оставаться видимыми. Если сделать это грубо через шаблон или общий фильтр, легко сломать поиск, сортировку и виджеты. Ниже — рабочий способ, который можно контролировать по категориям и быстро проверить после внедрения.
Когда это действительно нужно
Чаще всего задача появляется в магазинах с разной логикой продаж: часть ассортимента продаётся со склада, часть — под заказ, а часть вообще не должна отвлекать покупателя наличием. Например, в категории «Распродажа» можно оставить только остатки, а в категории «Предзаказ» скрыть всё, что уже доступно на складе. Важно не путать эту задачу с глобальным скрытием отсутствующих товаров: здесь мы меняем поведение только для выбранных категорий.
Диагностика проблемы перед изменениями
Перед правкой кода проверьте, где именно сейчас формируется список товаров. В WooCommerce на вывод могут влиять тема, фильтры каталога, плагины для сортировки и кэш. Если товары в наличии уже скрываются где-то ещё, новый фильтр даст неожиданный результат.
- Откройте проблемную категорию в обычном каталоге и в режиме инкогнито.
- Проверьте, не включена ли опция скрытия отсутствующих товаров в настройках WooCommerce.
- Посмотрите, не меняет ли тема запрос через
pre_get_postsили собственные хуки каталога. - Если используется кэш страницы, очистите его до теста и после правки.
Если в админке товары помечены как «В наличии», но на витрине они не показываются, причина обычно не в карточке товара, а в логике основного запроса или в фильтре видимости.
Подходы: плагин, код или настройка темы
Для такой задачи есть три реалистичных варианта. Настройка WooCommerce подходит только для общего поведения магазина. Плагин удобен, если нужен интерфейс для контент-менеджера. Код — лучший вариант, если правило должно зависеть от конкретных категорий и не расползаться по сайту.
| Подход | Когда использовать | Минус |
|---|---|---|
| Настройки WooCommerce | Нужно скрыть отсутствующие товары везде | Не решает задачу выборочно по категориям |
| Плагин | Нужен интерфейс без правки кода | Дополнительная зависимость и риск конфликта |
| Код в дочерней теме или мини-плагине | Нужна точная логика по категориям | Требуется аккуратное тестирование |
Пошаговое решение через фильтр WooCommerce
Ниже пример, который скрывает товары в наличии только в выбранных категориях. Логика строится на фильтре woocommerce_product_is_visible. Он срабатывает при формировании каталога и позволяет убрать товар из выдачи, не меняя саму карточку товара.
<?php
add_filter( 'woocommerce_product_is_visible', 'wpcore_hide_instock_products_in_selected_categories', 10, 2 );
function wpcore_hide_instock_products_in_selected_categories( $visible, $product_id ) {
if ( ! $visible ) {
return $visible;
}
if ( is_admin() ) {
return $visible;
}
$target_categories = array( 'pre-order', 'clearance' );
if ( ! has_term( $target_categories, 'product_cat', $product_id ) ) {
return $visible;
}
$product = wc_get_product( $product_id );
if ( ! $product ) {
return $visible;
}
if ( $product->is_in_stock() ) {
return false;
}
return $visible;
}
Что делает этот код: если товар относится к одной из указанных категорий и при этом находится в наличии, он не попадёт в каталог. Товары без остатка останутся видимыми. Если вам нужно обратное поведение, условие можно инвертировать.
Если нужно скрывать именно товары без остатка
Иногда задача формулируется наоборот: в отдельных категориях показывать только товары в наличии, а отсутствующие убирать. Тогда меняется только проверка статуса склада.
<?php
add_filter( 'woocommerce_product_is_visible', 'wpcore_hide_outofstock_products_in_selected_categories', 10, 2 );
function wpcore_hide_outofstock_products_in_selected_categories( $visible, $product_id ) {
if ( ! $visible || is_admin() ) {
return $visible;
}
$target_categories = array( 'sale', 'featured' );
if ( ! has_term( $target_categories, 'product_cat', $product_id ) ) {
return $visible;
}
$product = wc_get_product( $product_id );
if ( ! $product ) {
return $visible;
}
if ( ! $product->is_in_stock() ) {
return false;
}
return $visible;
}
Как проверить, что решение сработало
Проверка должна быть не только визуальной. Иначе можно пропустить ситуацию, когда товар исчез из каталога, но остался в поиске или в блоке «Похожие товары».
- Откройте категорию, на которую распространяется правило.
- Сравните товары в наличии и без остатка: должны остаться только те, которые соответствуют условию.
- Проверьте поиск по сайту и страницу товара напрямую по URL.
- Если используются фильтры по атрибутам, убедитесь, что скрытые товары не возвращаются в выдаче фильтра.
- Очистите кэш страницы и объектный кэш, если он есть.
Для быстрой диагностики можно временно вывести статус товара в шаблоне категории или в лог. Если товар виден в админке, но не проходит фильтр, обычно проблема в неверном slug категории или в том, что товар принадлежит не только целевой категории.
Частые ошибки и как их исправить
Используют название категории вместо slug
Функция has_term() надёжнее работает со slug. Если передать русское название категории, совпадение может не сработать, особенно после переименования термина. Проверьте slug в разделе «Товары → Категории».
Ставят код в тему без учёта обновлений
Если код добавлен прямо в functions.php родительской темы, он может потеряться при обновлении. Для таких правок лучше использовать дочернюю тему или небольшой must-use плагин.
Не учитывают кэш и AJAX-фильтры
Некоторые темы и плагины строят каталог через AJAX. В этом случае товар может исчезнуть на основной странице, но остаться в подгружаемом блоке. После внедрения проверьте и обычный архив, и AJAX-фильтрацию, и результаты поиска.
Путают видимость товара и остаток
Статус in stock не равен «показывать в каталоге». Товар может быть в наличии, но скрыт настройками видимости, каталогом по ролям или отдельным плагином. Если правило не работает, сначала проверьте саму карточку товара в WooCommerce.
Если нужен более управляемый вариант
Когда правило должно редактироваться менеджером без разработчика, удобнее вынести список категорий в настройку или использовать плагин с интерфейсом. Но если задача простая и завязана на конкретные категории, код остаётся самым предсказуемым вариантом. Важно только не разбрасывать его по нескольким местам: один фильтр, одна точка правды.
Безопасность и производительность
Фильтр woocommerce_product_is_visible вызывается часто, поэтому не стоит добавлять в него тяжёлые запросы к базе или внешние HTTP-вызовы. Используйте только то, что уже есть в WooCommerce: wc_get_product(), has_term() и простую проверку статуса. Если категорий много и логика сложнее, лучше заранее собрать список целевых term ID и не вычислять его на каждом запросе.
Если магазин большой, после внедрения проверьте время загрузки каталога и работу кэша. В большинстве случаев такой фильтр не создаёт заметной нагрузки, но на сайтах с большим количеством товаров и сложными фильтрами любая дополнительная проверка в цикле может стать ощутимой.
Когда лучше не скрывать товары кодом
Если маркетинг регулярно меняет правила показа, а каталог управляется контент-менеджерами, жёсткая логика в коде быстро станет неудобной. В таком случае лучше использовать настройку в админке или отдельный плагин с понятным интерфейсом. Код хорош там, где правило стабильно и его не нужно объяснять каждый раз заново.