Диагностика задачи: зачем исключать доставку для отдельных товаров
В стандартной логике WooCommerce доставка рассчитывается на весь заказ целиком, без исключений. Однако бывают ситуации, когда нужно запретить доставку для конкретных товаров. Например, цифровые товары, услуги или товары с самовывозом. Без правильной настройки покупатель может столкнуться с невозможностью оформить заказ или с некорректной стоимостью доставки.
Пошаговое решение: запрет доставки для выбранных товаров через код
Шаг 1. Определяем ID товаров для исключения
Для начала нужно знать ID товаров, для которых доставка запрещена. Можно посмотреть ID в админке WooCommerce в списке товаров или на странице редактирования товара.
Шаг 2. Используем хук woocommerce_package_rates для фильтрации вариантов доставки
Хук позволяет изменить доступные способы доставки перед выводом покупателю. Мы проверим содержимое корзины и если в ней есть запрещённые товары, удалим все способы доставки, чтобы покупатель не мог выбрать доставку.
Пример кода:
add_filter('woocommerce_package_rates', 'wp24_disable_shipping_for_specific_products', 10, 2);function wp24_disable_shipping_for_specific_products($rates, $package) { // Массив ID товаров, для которых нужно запретить доставку $excluded_products = array(123, 456, 789); $cart_items = WC()->cart->get_cart(); foreach ($cart_items as $cart_item) { if (in_array($cart_item['product_id'], $excluded_products)) { // Удаляем все тарифы доставки return array(); } } return $rates;}Шаг 3. Добавляем уведомление для пользователя
Пользователь должен понять, почему доставка недоступна. Добавим сообщение в корзину или на страницу оформления заказа.
add_action('woocommerce_check_cart_items', 'wp24_notify_shipping_disabled');function wp24_notify_shipping_disabled() { $excluded_products = array(123, 456, 789); foreach (WC()->cart->get_cart() as $cart_item) { if (in_array($cart_item['product_id'], $excluded_products)) { wc_print_notice(__('Обратите внимание: для выбранных товаров доставка не доступна.'), 'notice'); break; } }}Проверка результата после внедрения
1. Добавьте в корзину товар с ID из массива $excluded_products. 2. Перейдите в корзину и оформление заказа. 3. Убедитесь, что варианты доставки не отображаются. 4. Убедитесь, что выводится уведомление о недоступности доставки.
Для товаров, не входящих в список исключений, варианты доставки должны отображаться как обычно.
Частые ошибки и как их исправить
- Ничего не произошло после добавления кода: Проверьте, что код добавлен в файл
functions.phpвашей активной темы или в кастомный плагин, и что WooCommerce активен. - Уведомление не отображается: Убедитесь, что вызов
wc_print_noticeпроисходит в подходящем хуке (woocommerce_check_cart_items), и что не отключены уведомления в настройках WooCommerce. - Доставка не отключается, если товар в корзине с вариациями: В таком случае нужно проверять
variation_id, а не толькоproduct_id. Можно расширить проверку так:if (in_array($cart_item['product_id'], $excluded_products) || in_array($cart_item['variation_id'], $excluded_products)) { ... } - Конфликты с плагинами доставки: Некоторые сторонние плагины могут перезаписывать методы расчёта доставки. В этом случае код нужно адаптировать под API конкретного плагина.
Практические советы по производительности и безопасности
- Сохраняйте список товаров для исключения в настройках темы или отдельном файле конфигурации, чтобы не править код постоянно.
- Для больших магазинов с сотнями товаров лучше использовать категории или мета-поля для группировки товаров без доставки и проверять по ним, чтобы не держать длинные массивы ID в коде.
- Всегда тестируйте изменения на копии сайта или в staging-среде, чтобы избежать сбоев на рабочем сайте.
- Используйте
current_user_can()и nonce для защиты действий, если расширяете функционал UI для управления этими товарами.
Сравнение вариантов решения
| Метод | Преимущества | Недостатки |
|---|---|---|
Код на фильтре woocommerce_package_rates | Легко кастомизировать, не требует плагинов, быстро работает | Требует навыков PHP, неочевиден для менеджера магазина |
| Использование плагинов (например, Conditional Shipping) | Удобный UI, много условий | Дополнительная нагрузка, стоимость, лишние зависимости |
| Использование категории для исключения доставки | Простая логика, можно динамически менять товары | Требуется дополнительная проверка в коде, если корзина смешанная |