Диагностика проблемы: почему нужно исключать товары по атрибуту из корзины
В WooCommerce часто возникает задача автоматически не допускать в корзину товары с определённым атрибутом, например, товары на распродаже, подарочные сертификаты или товары с ограничениями. Стандартными средствами WooCommerce такую фильтрацию в корзине сделать нельзя — требуется вмешательство через код.
Типичные симптомы:
- Покупатели добавляют товары с запрещённым атрибутом и оформляют заказ, что приводит к ошибкам на складе или в учёте;
- Необходимо ограничить комбинации товаров в корзине для бизнес-логики;
- Нужно предупредить пользователя о недопустимых товарах и автоматически их удалять.
Как определить товары с нужным атрибутом в корзине WooCommerce
Атрибуты в WooCommerce хранятся как таксономии с префиксом pa_, например, pa_sale для атрибута «Распродажа». Чтобы проверить, есть ли товар с таким атрибутом, в цикле по товарам корзины получаем ID вариации или товара и вызываем функцию has_term().
function has_cart_item_attribute( $attribute_slug ) {
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product_id = $cart_item['product_id'];
if ( has_term( $attribute_slug, 'pa_' . $attribute_slug, $product_id ) ) {
return true;
}
}
return false;
}
Однако в этой функции есть ошибка: таксономия не может совпадать с слагом атрибута, надо передавать корректный слаг таксономии и значение терма. Правильнее проверять так:
$attribute_taxonomy = 'pa_sale'; // таксономия атрибута
$term_slug = 'yes'; // значение атрибута
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product_id = $cart_item['product_id'];
if ( has_term( $term_slug, $attribute_taxonomy, $product_id ) ) {
// товар с этим атрибутом
}
}
Пошаговое решение: исключение товаров с определённым атрибутом из корзины
- Подключить фильтр
woocommerce_check_cart_itemsдля проверки корзины при обновлении. - Пройти по всем товарам в корзине и выявить те, что имеют запрещённый атрибут.
- Удалить такие товары из корзины с помощью метода
remove_cart_item(). - Вывести уведомление об удалении товаров пользователю через
wc_add_notice().
add_action( 'woocommerce_check_cart_items', 'exclude_products_by_attribute_from_cart' );
function exclude_products_by_attribute_from_cart() {
$attribute_taxonomy = 'pa_sale'; // таксономия атрибута
$term_slug = 'yes'; // запрещённое значение
$cart = WC()->cart;
$items_to_remove = [];
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
if ( has_term( $term_slug, $attribute_taxonomy, $product_id ) ) {
$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( 'Товары с атрибутом "Распродажа" не могут быть добавлены в корзину и были удалены.', 'error' );
}
}
Проверка результата после внедрения
- Добавьте в каталог товар с атрибутом
pa_saleи значениемyes. - Попробуйте добавить этот товар в корзину — он должен появиться, но сразу после обновления корзины удалиться с ошибкой.
- Добавьте товар без этого атрибута — он должен остаться в корзине.
- Проверьте, что в админке WooCommerce заказы формируются без запрещённых товаров.
Частые ошибки и как их исправить
- Неверное имя таксономии или терма: Убедитесь, что атрибут зарегистрирован как
pa_имяв WooCommerce, а терм — именно тот, что вы проверяете. - Удаление товара не срабатывает: Используйте
remove_cart_item()с правильным ключом, а не ID продукта. - Сообщение об ошибке не появляется: Для вывода уведомлений используйте
wc_add_notice()с типомerror. - Кеширование мешает обновлению корзины: Отключите кеширование страниц с корзиной и оформлением заказа.
Практические советы по производительности и безопасности
- Минимизируйте количество запросов к базе: проверяйте атрибуты товаров в одном цикле.
- Обрабатывайте исключение товаров на этапе добавления в корзину с помощью
woocommerce_add_to_cart_validation, чтобы не добавлять запрещённые товары сразу. - Тестируйте код в дочерней теме или плагине, чтобы не потерять изменения при обновлении.
Дополнительный пример: блокировка добавления товара с атрибутом
add_filter( 'woocommerce_add_to_cart_validation', 'block_add_to_cart_for_attribute', 10, 3 );
function block_add_to_cart_for_attribute( $passed, $product_id, $quantity ) {
$attribute_taxonomy = 'pa_sale';
$term_slug = 'yes';
if ( has_term( $term_slug, $attribute_taxonomy, $product_id ) ) {
wc_add_notice( 'Товар с атрибутом "Распродажа" нельзя добавить в корзину.', 'error' );
return false;
}
return $passed;
}
Сравнение способов исключения товаров по атрибуту из корзины
| Метод | Плюсы | Минусы | Когда применять |
|---|---|---|---|
| Удаление после добавления (через woocommerce_check_cart_items) | Простота реализации Удаляет уже добавленные товары | Плохой UX — товар сначала добавляется, потом удаляется Нагрузка на корзину | Если нельзя блокировать добавление Нужна проверка всей корзины |
| Блокировка добавления (через woocommerce_add_to_cart_validation) | Лучший UX — сразу нельзя добавить Меньше нагрузки | Не проверяет товары, уже в корзине Требует очистки корзины вручную | Для запрета новых добавлений |