wp-lessons.ru wordpress WP-Lessons

Как скрыть нулевые товары в WooCommerce из каталога и поиска

Ситуация типовая: товар закончился, но продолжает висеть в каталоге, попадать в поиск и собирать клики в карточку, где покупатель видит сообщение о недоступности. Для магазина это лишний шум в аналитике и лишние вопросы в поддержку. Если задача именно в том, чтобы скрыть товары с нулевым остатком, а не просто отключить покупку, лучше решать её на уровне WooCommerce-запросов и карточки товара, а не вручную прятать позиции в админке.

Ниже — рабочий вариант без выдуманных хуков и без привязки к сторонним плагинам. Он подходит, если у вас включён учёт склада в WooCommerce и товары помечаются как отсутствующие на складе.

Когда проблема действительно в нулевых остатках

Сначала проверьте, что именно происходит у вас. Иногда товар «пропадает» не из-за остатка, а из-за фильтров темы, кэша или настроек видимости.

  • Товар имеет статус outofstock, но всё ещё отображается в архиве товаров.
  • Поиск WordPress находит карточку, хотя покупать её нельзя.
  • Категории показывают старые позиции после обновления остатков.
  • В карточке товара есть кнопка покупки, но при добавлении в корзину WooCommerce блокирует заказ.

Что проверить в админке WooCommerce

Откройте WooCommerce → Настройки → Товары → Запасы и убедитесь, что включён учёт запасов. Дальше проверьте сам товар: в блоке данных товара должен быть указан остаток, а статус склада — В наличии или Нет в наличии. Если учёт запасов выключен, код ниже не даст ожидаемого результата, потому что WooCommerce не будет считать товар отсутствующим по складу.

Пошаговое решение: скрываем товары с нулевым остатком

Логика простая: исключаем товары со статусом outofstock из основных витринных запросов и отдельно убираем их из поиска. Это не ломает карточку товара напрямую, но делает так, чтобы покупатель не попадал на недоступные позиции из каталога.

Добавьте код в functions.php дочерней темы или в собственный мини-плагин. Второй вариант надёжнее: код не потеряется при смене темы.

add_action( 'woocommerce_product_query', 'wp_lessons_hide_outofstock_products' );
function wp_lessons_hide_outofstock_products( $q ) {
    if ( is_admin() ) {
        return;
    }

    $meta_query = (array) $q->get( 'meta_query' );
    $meta_query[] = array(
        'key'     => '_stock_status',
        'value'   => 'outofstock',
        'compare' => '!='
    );

    $q->set( 'meta_query', $meta_query );
}

add_action( 'pre_get_posts', 'wp_lessons_hide_outofstock_from_search' );
function wp_lessons_hide_outofstock_from_search( $query ) {
    if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
        return;
    }

    $post_type = $query->get( 'post_type' );
    if ( empty( $post_type ) ) {
        $query->set( 'post_type', 'product' );
    }

    $meta_query = (array) $query->get( 'meta_query' );
    $meta_query[] = array(
        'key'     => '_stock_status',
        'value'   => 'outofstock',
        'compare' => '!='
    );

    $query->set( 'meta_query', $meta_query );
}

Этот вариант работает в большинстве стандартных сценариев, но у него есть важная оговорка: он влияет на запросы витрины и поиска, а не на все возможные места вывода товаров. Если тема или плагин строит собственный запрос, его может понадобиться донастроить отдельно.

Если нужно скрывать товар полностью, а не только из каталога

Иногда задача жёстче: товар должен исчезать не только из архива и поиска, но и из связанных товаров, рекомендаций и блоков WooCommerce. В таком случае удобнее использовать фильтр видимости товара. WooCommerce умеет хранить видимость через таксономию product_visibility, и это более корректный путь, чем пытаться вручную править каждый шаблон.

add_action( 'woocommerce_product_set_stock_status', 'wp_lessons_sync_visibility_for_outofstock', 10, 3 );
function wp_lessons_sync_visibility_for_outofstock( $product_id, $stock_status, $product ) {
    if ( 'outofstock' === $stock_status ) {
        wp_set_object_terms( $product_id, 'exclude-from-catalog', 'product_visibility', true );
        wp_set_object_terms( $product_id, 'exclude-from-search', 'product_visibility', true );
    } else {
        wp_remove_object_terms( $product_id, 'exclude-from-catalog', 'product_visibility' );
        wp_remove_object_terms( $product_id, 'exclude-from-search', 'product_visibility' );
    }
}

Здесь есть нюанс: не все магазины хотят автоматически менять видимость при каждом изменении склада. Если у вас есть товары под заказ или предзаказ, такой подход может скрыть то, что должно оставаться доступным. В этом случае лучше ограничиться только витриной и поиском.

Сравнение подходов

ПодходЧто делаетПлюсыМинусы
Настройки WooCommerceРучное скрытие товара в админкеБез кода, быстроНе масштабируется, легко забыть обновить статус
Фильтр запросовУбирает outofstock из каталога и поискаГибко, не трогает карточку товараНужно проверить тему и кэш
Изменение видимостиСкрывает товар шире по витринеПодходит для жёсткого сценарияМожет затронуть предзаказы и связанные товары

Как проверить, что решение сработало

После внедрения не ограничивайтесь визуальной проверкой главной страницы. Нужны несколько точек контроля.

  1. Откройте категорию, где есть товар с нулевым остатком, и убедитесь, что он не отображается.
  2. Проверьте поиск по названию товара: карточка не должна появляться в результатах.
  3. Если товар уже был в кеше, очистите кэш страницы и объектный кэш, если он используется.
  4. Откройте саму карточку товара по прямой ссылке: она может оставаться доступной, если вы не скрывали её полностью.
  5. Проверьте связанные товары и блоки рекомендаций на странице товара.

Для быстрой диагностики полезно временно вывести значение мета-поля _stock_status у проблемного товара через get_post_meta() или посмотреть его в базе. Если там не outofstock, код выше просто не сработает, и причину нужно искать в синхронизации склада.

Частые ошибки и как их исправить

Товар не исчезает из каталога

Чаще всего причина в кэше или в том, что тема строит собственный запрос без стандартного woocommerce_product_query. Сначала очистите кэш, потом проверьте, не переопределяет ли тема шаблоны архива товаров.

Товар пропал, хотя должен быть доступен под заказ

Значит, вы слишком агрессивно скрываете всё, что не в наличии. Для товаров под заказ лучше не использовать автоматическое исключение из каталога, а показывать отдельный статус наличия и отключать только кнопку покупки.

Поиск WordPress всё ещё находит карточку

Некоторые темы используют не стандартный поиск WooCommerce, а собственный AJAX-поиск. Тогда нужен отдельный фильтр именно для этого поиска. Универсального решения без знания конкретного плагина тут нет.

После обновления склада товар не возвращается в каталог

Это бывает, если вы добавили только скрытие, но не сделали обратное снятие термов видимости. В таком случае товар остаётся исключённым даже после появления остатка. Проверьте, что код обрабатывает оба состояния.

Безопасность и производительность

Если товаров много, не стоит каждый раз делать тяжёлые запросы к базе на фронтенде. Используйте стандартные хуки WooCommerce, а не ручной перебор всех товаров на каждой странице. Код выше работает через модификацию запроса и не сканирует каталог целиком.

Ещё один практический момент: если вы часто меняете остатки через импорт, проверьте, как обновляется поле _stock_status. При кривом импорте можно получить ситуацию, когда остаток уже нулевой, а статус всё ещё instock. Тогда скрытие не сработает, потому что проблема не в витрине, а в данных.

Если вам нужно не только скрытие, но и чистка дублей, лишних мета-данных и мусора в магазине, иногда удобнее закрыть часть таких задач отдельным инструментом вроде Clearfy Pro, но саму логику скрытия товаров с нулевым остатком всё равно лучше держать в коде и проверять на своём сценарии.

×

AI-плагин

WPGPT
Сам создает статьи для вашего сайта WordPress

SEO и мета-теги

Парсинг конкурентов

Изображения

Комментарии

Подробнее