WooCommerce: как отключить отложенные заказы для определённых товаров

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

Ниже — рабочий вариант без выдуманных хуков и без привязки к сторонним плагинам. Логика простая: если товар попадает в список исключений, покупатель не сможет оформить его как отложенный заказ. При этом обычная покупка для остальных товаров продолжит работать.

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

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

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

Диагностика проблемы: где именно ломается сценарий

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

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

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

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

add_action('woocommerce_before_cart', function () {
    if ( ! WC()->cart ) {
        return;
    }

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $product_id = $cart_item['product_id'];
        error_log('Cart product ID: ' . $product_id);
    }
});

Такой код нужен только для проверки на тестовом сайте. В продакшене его лучше убрать.

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

1. Определите список товаров или категорий

Самый надёжный подход — хранить исключения в массиве. Для небольшого каталога подойдут ID товаров. Если ассортимент меняется часто, удобнее проверять категории.

Ниже пример, где отложенный заказ запрещается для конкретных товаров и для всей категории preorder.

function wpbono_is_restricted_for_backorder( $product_id ) {
    $restricted_products   = array( 123, 456, 789 );
    $restricted_categories = array( 'preorder', 'custom-order' );

    if ( in_array( $product_id, $restricted_products, true ) ) {
        return true;
    }

    if ( has_term( $restricted_categories, 'product_cat', $product_id ) ) {
        return true;
    }

    return false;
}

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

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

add_filter( 'woocommerce_add_to_cart_validation', function ( $passed, $product_id, $quantity ) {
    if ( wpbono_is_restricted_for_backorder( $product_id ) ) {
        wc_add_notice(
            __( 'Этот товар нельзя оформить как отложенный заказ. Свяжитесь с менеджером для уточнения условий.', 'textdomain' ),
            'error'
        );
        return false;
    }

    return $passed;
}, 10, 3 );

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

3. Не давайте оформить смешанную корзину

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

add_action( 'woocommerce_check_cart_items', function () {
    if ( ! WC()->cart ) {
        return;
    }

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $product_id = $cart_item['product_id'];

        if ( wpbono_is_restricted_for_backorder( $product_id ) ) {
            wc_add_notice(
                __( 'В корзине есть товар, который нельзя оформить как отложенный заказ. Уберите его или оформите отдельно.', 'textdomain' ),
                'error'
            );
            break;
        }
    }
});

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

4. Спрячьте кнопку покупки для конкретных товаров

Если задача — не только блокировать оформление, но и не провоцировать пользователя на лишние действия, можно убрать кнопку покупки на странице товара. Это не защита само по себе, а именно UX-слой поверх проверки.

add_filter( 'woocommerce_is_purchasable', function ( $purchasable, $product ) {
    if ( $product instanceof WC_Product && wpbono_is_restricted_for_backorder( $product->get_id() ) ) {
        return false;
    }

    return $purchasable;
}, 10, 2 );

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

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

ПодходЧто делаетПлюсыМинусы
Проверка при добавлении в корзинуСразу блокирует проблемный товарПонятная ошибка для пользователя, меньше мусора в корзинеНе подходит, если товар нужно оставить в корзине
Проверка на этапе оформленияНе даёт завершить заказМожно смешивать товары до момента checkoutПользователь узнаёт о проблеме позже
Скрытие purchasableПрячет покупку на уровне товараЧистый интерфейсСлишком жёстко, если нужен частичный сценарий

Как проверить, что всё работает

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

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

Если используете кэширование страниц, обязательно очистите кэш после правки. Иначе можно решить, что код не работает, хотя на самом деле браузер или сервер отдают старую версию шаблона.

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

Проверяют не тот ID

В WooCommerce у вариативного товара есть родительский ID и ID вариации. Если вы проверяете только product_id, а правило должно работать на уровне вариации, логика может не сработать. В этом случае нужно отдельно учитывать variation_id из элемента корзины.

Скрывают кнопку, но не блокируют оформление

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

Ставят слишком общий запрет

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

Не тестируют корзину с несколькими товарами

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

Практические советы по безопасности и производительности

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

Для админки удобнее документировать правило прямо в коде: что именно считается запрещённым, почему и кто отвечает за обновление списка. Это снижает риск случайного удаления нужной категории при редактировании каталога.

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

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

WooCommerce: как автоматически удалять товар из корзины после оплаты
13.07.2026
WooCommerce: как настроить отправку уведомлений о заказах в Telegram
30.04.2026
WooCommerce: как запретить повторное создание заказа при наличии активного
09.06.2026
WooCommerce: как отключить отложенные заказы для определённых товаров
09.08.2026
Как создать нетипичный файловый хендлер в WordPress для обработки нестандартных типов файлов
24.03.2026