Как отключить покупку для отдельных товаров в WooCommerce без скрытия карточки

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

Ниже — рабочий способ отключить покупку точечно: для одного товара, для набора товаров по ID или по условию. Без выдуманных хуков и без вмешательства в ядро WooCommerce.

Когда это действительно нужно

Отключение покупки для отдельного товара полезно, когда карточка должна жить, а кнопка «В корзину» — нет. Обычно это один из таких случаев:

  • товар есть в каталоге, но продажа идёт только через менеджера;
  • позиция временно недоступна, но удалять её нельзя из-за SEO и истории;
  • нужен образец, демо-версия или бесплатная выдача без оформления заказа;
  • товар продаётся только в составе комплекта, а отдельно — нет;
  • нужно отключить покупку для конкретных вариаций, но оставить остальные.

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

Диагностика проблемы: что именно нужно отключить

В WooCommerce есть несколько разных уровней «нельзя купить», и их часто путают. Перед правкой проверьте, что именно вы хотите убрать:

1. Скрыть кнопку покупки

Карточка видна, но кнопка Добавить в корзину не показывается. Это самый частый сценарий.

2. Запретить добавление в корзину

Даже если кто-то вызовет URL добавления вручную, товар не должен попасть в корзину. Это уже не только интерфейс, но и логика.

3. Отключить покупку только для части вариаций

У вариативного товара иногда нужно оставить доступными не все размеры или цвета. Тогда работать надо аккуратнее, чтобы не сломать выбор вариаций.

4. Оставить покупку, но заменить сценарий

Например, вместо кнопки покупки показать кнопку «Запросить цену» или ссылку на форму. Это уже не просто запрет, а замена поведения.

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

Пошаговое решение через код

Самый надёжный вариант — пометить нужный товар как непокупаемый через фильтры WooCommerce. Для этого не надо трогать базу данных и не надо отключать весь магазин.

Вариант 1: отключить покупку для конкретного товара по ID

Добавьте код в functions.php дочерней темы или в свой небольшой плагин. Пример ниже отключает покупку для товара с ID 123:

add_filter( 'woocommerce_is_purchasable', 'wphelper_disable_purchase_for_product', 10, 2 );
function wphelper_disable_purchase_for_product( $purchasable, $product ) {
    if ( ! $product instanceof WC_Product ) {
        return $purchasable;
    }

    $blocked_ids = array( 123 );

    if ( in_array( $product->get_id(), $blocked_ids, true ) ) {
        return false;
    }

    return $purchasable;
}

Этот фильтр убирает возможность покупки на уровне WooCommerce. В большинстве тем кнопка «В корзину» исчезнет автоматически.

Вариант 2: отключить покупку по метке или категории

Если у вас не один товар, а целая группа, удобнее ориентироваться на категорию. Например, всё в категории no-buy должно быть недоступно для покупки:

add_filter( 'woocommerce_is_purchasable', 'wphelper_disable_purchase_for_category', 10, 2 );
function wphelper_disable_purchase_for_category( $purchasable, $product ) {
    if ( ! $product instanceof WC_Product ) {
        return $purchasable;
    }

    if ( has_term( 'no-buy', 'product_cat', $product->get_id() ) ) {
        return false;
    }

    return $purchasable;
}

Такой подход удобнее для контент-менеджера: достаточно назначить нужную категорию, и логика сработает без ручного редактирования кода.

Вариант 3: заменить кнопку на свой текст

Если товар нельзя купить, но вы хотите показать понятное сообщение, можно заменить кнопку на текст или ссылку. Например, для карточки товара:

add_action( 'woocommerce_single_product_summary', 'wphelper_show_not_for_sale_notice', 31 );
function wphelper_show_not_for_sale_notice() {
    global $product;

    if ( ! $product instanceof WC_Product ) {
        return;
    }

    if ( ! $product->is_purchasable() ) {
        echo '<p class="woocommerce-info">Товар доступен только по запросу. Свяжитесь с менеджером для уточнения условий.</p>';
    }
}

Это не заменяет запрет покупки, а дополняет его. Пользователь видит, что произошло, а не просто пустое место вместо кнопки.

Если нужно убрать покупку только у вариативного товара

С вариативными товарами важно не переборщить. Если отключить покупку у всего родителя, WooCommerce может скрыть кнопку целиком. Но иногда нужно оставить товар видимым и убрать только недоступные вариации. В таком случае лучше работать с конкретными вариациями, а не с родительским товаром.

Пример: отключаем покупку для вариации с ID 456:

add_filter( 'woocommerce_is_purchasable', 'wphelper_disable_purchase_for_variation', 10, 2 );
function wphelper_disable_purchase_for_variation( $purchasable, $product ) {
    if ( ! $product instanceof WC_Product ) {
        return $purchasable;
    }

    if ( $product->is_type( 'variation' ) && $product->get_id() === 456 ) {
        return false;
    }

    return $purchasable;
}

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

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

ПодходЧто делаетПлюсыМинусы
Скрыть товар в каталогеУбирает карточку из витриныПростоТеряется SEO и прямой трафик
Отключить покупку через кодОставляет карточку, но убирает покупкуГибко, надёжноНужно тестировать тему и шаблоны
Плагин для каталога/ролиДаёт интерфейс управленияУдобно для контент-менеджераЛишняя зависимость и возможные конфликты

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

Проверка результата после внедрения

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

  • откройте карточку товара в обычном режиме и убедитесь, что кнопка покупки исчезла или заменена;
  • попробуйте добавить товар в корзину через прямую ссылку вида ?add-to-cart=123;
  • проверьте товар в каталоге, на странице категории и в блоках с похожими товарами;
  • если это вариативный товар, переключите все доступные вариации;
  • очистите кэш страницы, если используется кэширование на уровне плагина или сервера.

Полезно проверить и фронтенд, и админку. Иногда товар выглядит недоступным на сайте, но всё ещё попадает в корзину через старую сессию или закэшированную страницу.

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

Код добавили в родительскую тему

После обновления тема перезапишет изменения. Для таких правок используйте дочернюю тему или отдельный мини-плагин.

Скрыли кнопку только CSS-ом

Это косметика, а не защита. Пользователь всё ещё может добавить товар в корзину через прямой запрос или старую кнопку из кэша.

Не учли кэш

Если страница товара кэшируется, кнопка может остаться видимой до сброса кэша. После правки очистите кэш плагина, сервера и CDN, если он есть.

Сломали вариативный товар

Частая причина — фильтр применили к родителю, хотя нужно было работать с вариацией. Проверьте тип объекта через $product->is_type().

Использовали неправильный ID

В WooCommerce есть ID товара, ID вариации и ID поста в базе. Для вариативных товаров это не одно и то же. Перед правкой откройте карточку в админке и сверяйте именно тот объект, который хотите отключить.

Что учесть для безопасности и производительности

Сам фильтр woocommerce_is_purchasable лёгкий и не создаёт заметной нагрузки, если не делать внутри него тяжёлые запросы к базе. Не тяните в него сложные SQL-запросы, внешние API и проверку десятков мета-полей на каждом хите.

Если логика зависит от категории, списка ID или метки, держите этот список в коде или в одной опции, а не собирайте его на лету. Для больших магазинов лучше заранее продумать структуру: например, отдельная категория для товаров «не для продажи» или флаг в метаполе, которое заполняет администратор.

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

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

Как запретить индексацию отдельных страниц в WordPress без плагинов
17.08.2026
Как избежать ошибок WooCommerce при массовом изменении цен товаров
30.04.2026
Как сделать производительный AJAX в WordPress без admin-ajax.php
06.04.2026
Как избежать конфликтов Ping в WordPress: практическое руководство
04.03.2026
WooCommerce: как проверить и исправить ошибку регистрации нового пользователя
09.05.2026