Диагностика задачи: зачем исключать товары из корзины по атрибутам
В WooCommerce иногда требуется ограничить корзину, например, запретить одновременную покупку товаров с определёнными характеристиками, или полностью исключить из оформления заказа товары с заданными атрибутами (например, товары с пометкой "Скидка" или "Промо" не должны попадать в корзину). Это полезно для контроля акций, предотвращения конфликтов товаров или соблюдения бизнес-правил.
Как определить товары с нужными атрибутами в корзине WooCommerce
Атрибуты товаров в WooCommerce хранятся в виде таксономий с префиксом pa_. Например, атрибут "Цвет" имеет таксономию pa_color. Чтобы проверить, есть ли в корзине товар с определённым значением атрибута, нужно пройтись по элементам корзины и проверить их атрибуты.
function has_product_with_attribute_in_cart( $taxonomy, $term_slug ) {
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product_id = $cart_item['product_id'];
if ( has_term( $term_slug, $taxonomy, $product_id ) ) {
return true;
}
}
return false;
}Этот код возвращает true, если в корзине есть товар с указанным атрибутом.
Пошаговое решение: исключаем товары с определённым атрибутом из корзины
Чтобы запретить оформление заказа, если в корзине есть товары с определённым атрибутом, или удалить их из корзины автоматически, можно использовать следующий подход.
1. Удаление товаров из корзины с атрибутом при обновлении корзины
add_action( 'woocommerce_before_calculate_totals', 'remove_products_with_attribute_from_cart', 10, 1 );
function remove_products_with_attribute_from_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
$taxonomy = 'pa_sale'; // пример атрибута
$term_slug = 'promo'; // значение атрибута, которое нужно исключить
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
if ( has_term( $term_slug, $taxonomy, $product_id ) ) {
$cart->remove_cart_item( $cart_item_key );
wc_add_notice( sprintf( 'Товар "%s" удалён из корзины, так как он запрещён для покупки.', $cart_item['data']->get_name() ), 'error' );
}
}
}2. Запрет оформления заказа (checkout) при наличии таких товаров
add_action( 'woocommerce_check_cart_items', 'prevent_checkout_with_restricted_products' );
function prevent_checkout_with_restricted_products() {
$taxonomy = 'pa_sale';
$term_slug = 'promo';
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product_id = $cart_item['product_id'];
if ( has_term( $term_slug, $taxonomy, $product_id ) ) {
wc_add_notice( 'Ваша корзина содержит товары, запрещённые к оформлению заказа.', 'error' );
break;
}
}
}Проверка результата после внедрения
- Добавьте в каталог продукт с атрибутом
pa_sale = promo. - Добавьте этот товар в корзину.
- Обновите корзину — товар должен быть автоматически удалён с уведомлением.
- Если вместо удаления используете только запрет оформления, попытайтесь перейти к оформлению заказа — вы должны увидеть ошибку.
- Проверьте, что товары без данного атрибута в корзине остаются без изменений.
Частые ошибки и как их исправить
- Неверное имя таксономии: Проверьте в админке WordPress, что имя атрибута начинается с
pa_и соответствует слугу атрибута. - Подстановка не того терма: Убедитесь, что передаёте корректный слаг терма (значение из списка атрибута), а не его имя.
- Кэширование корзины: Если изменения не применяются сразу, очистите кэш сайта и браузера.
- Хук срабатывает в админке: Добавляйте проверки
is_admin()иDOING_AJAX, чтобы не мешать работе админки.
Практические советы по производительности и безопасности
- Проверяйте наличие атрибутов только по ID продукта, а не по вариациям, если это допустимо, чтобы снизить нагрузку.
- Не используйте тяжелые SQL-запросы в хуках, срабатывающих на каждое обновление корзины.
- Добавляйте пользовательские уведомления через
wc_add_noticeдля лучшей UX, избегайте abrupt удалений без объяснений. - Если атрибутов много, кешируйте результаты
has_termдля каждого продукта при обработке корзины.
Сравнение способов исключения товаров с атрибутами из корзины
| Метод | Плюсы | Минусы |
|---|---|---|
| Автоматическое удаление товаров из корзины | Простота реализации, мгновенный эффект | Пользователь может быть недоволен внезапным удалением |
| Запрет оформления заказа с уведомлением | Пользователь видит причину, может изменить корзину | Требует дополнительных действий от пользователя |
| Вывод предупреждения, но без удаления и блокировки | Минимальное вмешательство | Пользователь может игнорировать предупреждение |