Диагностика проблемы: зачем исключать товары по атрибуту из корзины и оформления заказа
В интернет-магазинах на WooCommerce иногда возникает задача исключить из процесса покупки определённые товары или их варианты, если они имеют определённый атрибут. Например, товары с атрибутом "недоступен для онлайн-покупки" или с пометкой "только самовывоз" не должны попадать в корзину или не должны проходить дальше оформления заказа.
Стандартными средствами WooCommerce такая фильтрация не реализована. Если оставить товар в корзине, пользователь сможет оформить заказ, что приведёт к ошибкам в логистике или неудовлетворённости клиентов.
Как проверить, что товар по атрибуту попал в корзину
Для начала нужно понимать, что WooCommerce хранит атрибуты товаров в метаданных и терминах таксономий. Чтобы убедиться, что товар с нужным атрибутом есть в корзине, можно использовать следующий код-дебаг:
add_action('woocommerce_before_cart', function() {
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$product => $cart_item['data'];
$attributes = $product->get_attributes();
echo '<pre>';
print_r($attributes);
echo '</pre>';
}
});В результате на странице корзины вы увидите массив атрибутов каждого товара. Это поможет определить точное имя атрибута и его значение.
Пошаговое решение: исключение товаров по атрибуту из корзины и оформления заказа
1. Определяем атрибут и значение для исключения
Допустим, у нас есть атрибут pa_availability (па — префикс для Product Attribute), и мы хотим исключить товары с значением no-online.
2. Фильтрация добавления товара в корзину
Чтобы запретить добавление товара с таким атрибутом в корзину, используйте хук woocommerce_add_to_cart_validation:
add_filter('woocommerce_add_to_cart_validation', function($passed, $product_id, $quantity) {
$product = wc_get_product($product_id);
$attributes = $product->get_attributes();
if (isset($attributes['pa_availability'])) {
$terms = wp_get_post_terms($product_id, 'pa_availability', array('fields' => 'slugs'));
if (in_array('no-online', $terms)) {
wc_add_notice('Этот товар недоступен для онлайн-покупки.', 'error');
return false;
}
}
return $passed;
}, 10, 3);3. Исключение товара из корзины, если он там уже есть
Если товар уже в корзине (например, добавлен до внедрения проверки), нужно автоматически удалить его:
add_action('woocommerce_before_cart', function() {
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$product_id = $cart_item['product_id'];
$terms = wp_get_post_terms($product_id, 'pa_availability', array('fields' => 'slugs'));
if (in_array('no-online', $terms)) {
WC()->cart->remove_cart_item($cart_item_key);
wc_add_notice('Товар с ограничением онлайн-продажи был удалён из корзины.', 'notice');
}
}
});4. Проверка перед оформлением заказа
Для страховки добавьте проверку перед оформлением заказа, чтобы заблокировать оформление, если в корзине остались запрещённые товары:
add_action('woocommerce_check_cart_items', function() {
foreach (WC()->cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$terms = wp_get_post_terms($product_id, 'pa_availability', array('fields' => 'slugs'));
if (in_array('no-online', $terms)) {
wc_add_notice('В корзине есть товары, которые нельзя приобрести онлайн.', 'error');
break;
}
}
});Проверка результата после внедрения
- Попытайтесь добавить в корзину товар с атрибутом
pa_availability=no-online— он не должен добавиться, появится сообщение об ошибке. - Если такой товар уже в корзине, обновите страницу корзины — товар должен удалиться автоматически.
- Попытка оформить заказ с запрещённым товаром должна блокироваться с ошибкой.
Частые ошибки и как исправить
- Неправильное имя атрибута или его значение. Проверьте точное имя атрибута через админку или функцию
get_attributes(). - Атрибут задан в виде текстового поля, а не термина. В WooCommerce атрибуты бывают пользовательскими (пользовательский текст) и глобальными (терминами). Для фильтрации используйте именно термины.
- Кэширование корзины не обновляется. Очистите кэш браузера и серверный кэш (если используется).
- Конфликт с другими плагинами, которые управляют корзиной. Временно отключите сторонние плагины для теста.
Практические советы по безопасности и производительности
- Не добавляйте тяжелые запросы в хуки, которые срабатывают на каждом просмотре корзины — кэшируйте результаты, если товарная база большая.
- Используйте проверку не только по атрибуту, но и по статусу товара (
$product->is_purchasable()), чтобы избежать добавления недоступных товаров. - Для больших магазинов рассмотрите вариант кеширования атрибутов товаров, чтобы не выполнять лишних запросов к базе в цикле.
Сравнение способов исключения товаров по атрибуту
| Метод | Плюсы | Минусы |
|---|---|---|
| Фильтрация добавления в корзину (woocommerce_add_to_cart_validation) | Не допускает добавления запрещённых товаров, пользователь сразу получает ошибку | Не убирает товары, добавленные до внедрения |
| Удаление товаров из корзины (woocommerce_before_cart) | Автоматически очищает корзину от запрещённых товаров | Может создавать неудобства, если пользователь не сразу поймёт причину удаления |
| Проверка оформления заказа (woocommerce_check_cart_items) | Финальная страховка, блокирует заказ | Поздняя проверка, пользователь уже прошёл часть процесса |