Диагностика проблемы: зачем исключать доставку для отдельных товаров
В интернет-магазине на WooCommerce иногда возникает необходимость отключить опцию доставки для конкретных товаров. Например, для цифровых товаров, услуг, или товаров, которые клиент забирает самостоятельно. По умолчанию WooCommerce не предоставляет гибкой настройки для исключения доставки на уровне отдельных товаров, поэтому приходится использовать код.
Пошаговое решение: как отключить доставку для определённых товаров через functions.php
1. Определяем ID товаров для исключения
Сначала нужно узнать ID товаров, для которых необходимо выключить доставку. Это можно сделать в админке WooCommerce в списке товаров, наведя курсор на название товара.
2. Добавляем фильтр для исключения доставки
Добавьте следующий код в файл functions.php вашей дочерней темы или через специальный плагин для сниппетов:
add_filter('woocommerce_package_rates', 'disable_shipping_for_specific_products', 10, 2);function disable_shipping_for_specific_products($rates, $package) { $excluded_product_ids = array(123, 456); // Замените на ваши ID товаров foreach (WC()->cart->get_cart() as $cart_item) { if (in_array($cart_item['product_id'], $excluded_product_ids)) { // Удаляем все способы доставки return array(); } } return $rates;}Этот код проверяет содержимое корзины, и если в ней есть товар с ID из массива $excluded_product_ids, то список доступных способов доставки очищается.
3. Тестируем на разных товарах
Положите в корзину товар с ID, указанным в массиве, и убедитесь, что на странице оформления заказа способы доставки не отображаются. Для остальных товаров доставка должна работать как обычно.
Проверка результата после внедрения
- Добавьте в корзину товар с ID из списка исключений – доставка должна исчезнуть.
- Добавьте в корзину товар, не входящий в список – способы доставки должны отображаться.
- Добавьте одновременно исключённый и обычный товар – доставка отключена полностью (по умолчанию в WooCommerce корзина – одна посылка).
Частые ошибки и их исправление
- Неверные ID товаров: убедитесь, что вы используете именно ID товаров, а не SKU или другие параметры.
- Кэширование страниц: если изменения не видны, очистите кэш браузера, плагинов кеширования и CDN.
- Конфликт с плагинами доставки: некоторые расширения доставки могут игнорировать стандартные фильтры WooCommerce, в этом случае нужно отлаживать совместимость.
- Код добавлен в неправильное место: вставляйте код в
functions.phpдочерней темы, чтобы не потерять изменения при обновлении.
Практические советы по улучшению производительности и безопасности
- Добавляйте только необходимые ID товаров в массив, чтобы не нагружать проверку.
- Если товаров много, лучше использовать мета-поля или таксономии для маркировки товаров, а не жестко прописывать ID.
- Для безопасности избегайте исполнения пользовательского ввода в этом коде без проверки.
Альтернативные варианты реализации
| Способ | Преимущества | Недостатки |
|---|---|---|
| Код в functions.php | Бесплатно, гибко, без сторонних плагинов | Требует навыков программирования, может конфликтовать |
| Плагины доставки с настройками исключений | Простая настройка через админку | Дополнительный вес сайта, плата за расширенные функции |
| Использование атрибутов/меток товаров | Удобно для большого каталога, масштабируемо | Требует доработки кода для фильтрации по меткам |
Код с использованием мета-поля для исключения доставки
Можно добавить произвольное поле exclude_from_shipping (значение 1) для товаров и в коде проверять его:
add_filter('woocommerce_package_rates', 'disable_shipping_for_products_with_meta', 10, 2);function disable_shipping_for_products_with_meta($rates, $package) { foreach (WC()->cart->get_cart() as $cart_item) { $exclude = get_post_meta($cart_item['product_id'], 'exclude_from_shipping', true); if ('1' === $exclude) { return array(); } } return $rates;}Так вы избавляетесь от жёстко прописанных ID и управляете исключениями через админку.