Почему нужно исключать товары из корзины по атрибутам?
В интернет-магазинах на WooCommerce иногда требуется запретить добавление в корзину товаров с определёнными атрибутами. Например, товары с атрибутом "Скидка 50%" могут быть доступны только для просмотра, но не для покупки, или товары с атрибутом "Только под заказ" должны исключаться из стандартной корзины. Такой сценарий часто встречается при гибком управлении ассортиментом и маркетинговыми акциями.
Диагностика: как определить атрибуты товаров в корзине
Для начала нужно понять, какие атрибуты есть у товаров, и как WooCommerce хранит их данные. Атрибуты в WooCommerce — это термины таксономии, например, pa_color, pa_size. В корзине каждый объект содержит ID товара, но не сразу атрибуты.
Чтобы вывести атрибуты товаров в корзине для диагностики, можно использовать следующий код, добавив его в functions.php темы:
add_action('woocommerce_before_cart', function() {
foreach (WC()->cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
echo '<pre>';
print_r($product->get_attributes());
echo '</pre>';
}
});После этого на странице корзины вы увидите массивы атрибутов товаров. Это поможет определить ключи и значения атрибутов для фильтрации.
Пошаговое решение: исключение товаров из корзины по атрибутам
Основная идея — использовать хук woocommerce_check_cart_items для проверки корзины перед оформлением заказа и удалять товары с нужными атрибутами или блокировать оформление заказа.
Пример кода, который удаляет товары с атрибутом pa_discount со значением 50% из корзины с уведомлением:
add_action('woocommerce_check_cart_items', function() {
$cart = WC()->cart;
$items_to_remove = [];
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
if (isset($attributes['pa_discount'])) {
// Получаем значение атрибута из объекта WC_Product
$terms = wp_get_post_terms($product->get_id(), 'pa_discount', ['fields' => 'names']);
if (in_array('50%', $terms)) {
$items_to_remove[] = $cart_item_key;
}
}
}
if (!empty($items_to_remove)) {
foreach ($items_to_remove as $key) {
$cart->remove_cart_item($key);
}
wc_add_notice('Некоторые товары с атрибутом "Скидка 50%" были удалены из корзины.', 'error');
}
});Если нужно просто запретить оформление заказа, а не удалять товары, можно заменить логику на добавление wc_add_notice с ошибкой и вызовом wp_safe_redirect для возврата на страницу корзины.
Альтернативный способ: блокировка добавления в корзину
Чтобы предотвратить добавление товара с определённым атрибутом в корзину, используйте фильтр woocommerce_add_to_cart_validation:
add_filter('woocommerce_add_to_cart_validation', function($passed, $product_id) {
$terms = wp_get_post_terms($product_id, 'pa_discount', ['fields' => 'names']);
if (in_array('50%', $terms)) {
wc_add_notice('Товар с атрибутом "Скидка 50%" нельзя добавить в корзину.', 'error');
return false;
}
return $passed;
}, 10, 2);Проверка результата после внедрения
- Добавьте в корзину товар с атрибутом, который нужно исключить, и убедитесь, что он либо не добавляется, либо удаляется с сообщением.
- Попробуйте оформить заказ с таким товаром — должно появляться уведомление об ошибке.
- Проверьте, что товары без запрещённых атрибутов добавляются и оформляются без проблем.
- Просмотрите страницу корзины, чтобы убедиться, что изменения не влияют на другие товары.
Частые ошибки и как исправить
- Неверное имя атрибута: В WooCommerce атрибуты имеют префикс
pa_. Убедитесь, что используете правильный слаг (slug) атрибута, например,pa_color, а не простоcolor. - Атрибуты не передаются в объект WC_Product: Метод
get_attributes()возвращает массив объектов WC_Product_Attribute, а не значения термов. Для получения значений используйтеwp_get_post_terms(). - Удаление товара не работает: Убедитесь, что вы вызываете
$cart->remove_cart_item($cart_item_key)с правильным ключом корзины. - Сообщения не отображаются: Проверьте, что шаблон темы выводит уведомления WooCommerce, через функцию
wc_print_notices()илиwoocommerce_output_all_notices().
Практические советы по безопасности и производительности
- Не добавляйте тяжелые запросы к базе данных в хуки, которые вызываются часто (например, при каждом просмотре корзины). Используйте кеширование, если атрибуты проверяются часто.
- Избегайте удаления товаров из корзины без уведомления пользователя — это улучшит UX и снизит количество обращений в поддержку.
- Проверяйте совместимость с плагинами кэширования и оптимизации, чтобы динамические проверки корзины работали корректно.
- Если атрибуты часто меняются, рассмотрите создание отдельного метаполя для быстрого доступа вместо запросов по таксономиям.
Сравнение вариантов реализации
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Удаление товаров из корзины (woocommerce_check_cart_items) | Гарантированное удаление, можно показывать уведомление | Может раздражать пользователя, если товар уже добавлен | Если нельзя продавать товар в принципе |
| Блокировка добавления в корзину (woocommerce_add_to_cart_validation) | Пользователь сразу информирован, товар не попадает в корзину | Не помогает, если товар уже в корзине | Предотвратить добавление запрещённых товаров |
| Блокировка оформления заказа | Не удаляет товары, можно дать разъяснения | Пользователь может быть расстроен на последнем шаге | Если нужно разрешить просмотр, но не покупку |