Диагностика проблемы: почему варианты доставки не отключаются автоматически
В стандартном WooCommerce варианты доставки остаются активными, даже если в корзине есть товары, которых нет в наличии. Это приводит к путанице у покупателей и дополнительной работе для менеджеров. Необходима автоматизация, которая будет проверять наличие товаров в корзине и отключать методы доставки, если хотя бы один товар отсутствует на складе.
Как работает проверка наличия товаров в WooCommerce
WooCommerce хранит данные по запасам товаров в мета-данных каждого товара. При включённом управлении запасами ('manage_stock' => true) у каждого товара есть поле _stock, у вариаций — отдельные значения.
Для проверки наличия в корзине можно использовать глобальный объект WC()->cart и его методы.
Пошаговое решение: отключение вариантов доставки при отсутствии товаров в корзине
1. Использование хука woocommerce_package_rates
Этот фильтр позволяет менять список доступных вариантов доставки перед выводом. В него можно добавить проверку и удалить варианты по условию.
2. Код для отключения вариантов доставки
add_filter('woocommerce_package_rates', 'disable_shipping_if_out_of_stock', 10, 2);
function disable_shipping_if_out_of_stock($rates, $package) {
// Получаем корзину
$cart = WC()->cart->get_cart();
// Флаг для определения, есть ли в корзине отсутствующий товар
$out_of_stock_found = false;
foreach ($cart as $cart_item) {
$product = $cart_item['data'];
// Проверяем управление запасами и наличие
if ($product->managing_stock() && !$product->is_in_stock()) {
$out_of_stock_found = true;
break;
}
}
// Если есть отсутствующие товары, отключаем все варианты доставки
if ($out_of_stock_found) {
// Можно отключить все варианты
// или оставить только выбранные (например, самовывоз)
// В этом примере полностью отключаем
return array();
}
return $rates;
}
3. Настройка исключений: оставляем только самовывоз
Если нужно не полностью отключать доставку, а только оставить, например, самовывоз, используйте ID метода доставки:
add_filter('woocommerce_package_rates', 'disable_shipping_except_local_pickup', 10, 2);
function disable_shipping_except_local_pickup($rates, $package) {
$cart = WC()->cart->get_cart();
$out_of_stock_found = false;
foreach ($cart as $cart_item) {
$product = $cart_item['data'];
if ($product->managing_stock() && !$product->is_in_stock()) {
$out_of_stock_found = true;
break;
}
}
if ($out_of_stock_found) {
foreach ($rates as $rate_id => $rate) {
if ('local_pickup' !== $rate->method_id) {
unset($rates[$rate_id]);
}
}
}
return $rates;
}
Проверка результата после внедрения
- Добавьте в корзину товар с нулевым запасом (или отключите управление запасами и установите статус "нет в наличии")
- Перейдите на страницу оформления заказа и проверьте список доступных вариантов доставки
- Если всё сделано правильно, варианты доставки, кроме самовывоза (если настроено), должны исчезнуть
- Проверьте на товарах в наличии — варианты доставки должны отображаться как обычно
Частые ошибки и их исправление
- Ошибка: Варианты доставки не меняются — фильтр не срабатывает.
Причина: Код добавлен в неподходящее место (например, в плагин, который не активен) или приоритет фильтра слишком низкий.
Решение: Добавьте код в functions.php активной темы или создайте небольшой плагин, приоритет поставьте 10 или выше. - Ошибка: В корзине товары отображаются как в наличии, хотя на складе нулевой запас.
Причина: Управление запасами отключено для товара.
Решение: Включите управление запасами у товара или адаптируйте проверку под статус наличия ($product->is_in_stock()). - Ошибка: После отключения доставки сайт показывает пустую страницу оформления.
Причина: Нет доступных методов доставки, а WooCommerce по умолчанию требует минимум один.
Решение: Оставьте хотя бы один метод (например, самовывоз) или добавьте уведомление клиенту о проблеме с наличием.
Практические советы по безопасности и производительности
- Не делайте лишних запросов к базе — используйте объекты продуктов из корзины, а не загружайте товары заново.
- Проверяйте, что код не конфликтует с другими плагинами, меняющими методы доставки.
- Для сложных условий наличия можно кэшировать результаты проверки в сессии пользователя, чтобы не перегружать сервер.
- Добавьте уведомление в UI, если доставка отключена из-за отсутствия товара, чтобы не вводить пользователя в заблуждение.
Сравнение подходов: плагин vs собственный код
| Критерий | Плагин (например, WooCommerce Conditional Shipping) | Собственный код (решение из статьи) |
|---|---|---|
| Гибкость | Высокая, но ограничена функционалом плагина | Максимальная, можно реализовать любую логику |
| Производительность | Может добавлять нагрузку, зависит от плагина | Оптимизировано под конкретный кейс |
| Стоимость | Платные расширения могут стоить денег | Бесплатно, при наличии навыков разработки |
| Поддержка | Есть, но зависит от автора плагина | Своя ответственность за поддержку |