Диагностика задачи: зачем исключать товары с определёнными атрибутами из корзины
В интернет-магазинах на WooCommerce иногда требуется запретить покупку товаров с определёнными атрибутами в одной корзине или полностью блокировать добавление таких товаров. Например, если товар содержит атрибут «Тип: Скидка» или «Состояние: Распродажа», и вы хотите запретить их совместное приобретение с другими товарами или исключить из корзины. Это может быть связано с акциями, ограничениями поставщиков или логистикой.
Рассмотрим, как программно убрать из корзины товары с заданными атрибутами и уведомить пользователя.
Пошаговое решение: удаление товаров по атрибутам из корзины
1. Получение атрибутов товара в корзине
Для проверки атрибутов используем объект WC_Product из элемента корзины WC_Cart_Item. Атрибуты находятся в методе get_attributes(), но для пользовательских атрибутов лучше получить метаданные варианта или товара.
function has_attribute( $product, $attribute_name, $attribute_value ) {
$attributes = $product->get_attributes();
foreach ( $attributes as $attribute ) {
if ( $attribute->is_taxonomy() ) {
$terms = wp_get_post_terms( $product->get_id(), $attribute->get_name(), array('fields' => 'names') );
if ( in_array( $attribute_value, $terms, true ) ) {
return true;
}
} else {
// Для пользовательских атрибутов
if ( $attribute->get_name() === $attribute_name && $attribute->get_options() ) {
if ( in_array( $attribute_value, $attribute->get_options(), true ) ) {
return true;
}
}
}
}
return false;
}2. Фильтрация корзины и удаление товаров
Добавим проверку на событие woocommerce_before_calculate_totals, чтобы пройти по корзине и удалить товары с нужным атрибутом. Также уведомим пользователя через сессионное сообщение.
add_action( 'woocommerce_before_calculate_totals', 'remove_products_by_attribute_from_cart', 10, 1 );
function remove_products_by_attribute_from_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
$attribute_name = 'pa_sostoyanie'; // пример: slug атрибута
$attribute_value = 'rasprodazha'; // значение атрибута
$removed = false;
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
if ( has_attribute( $product, $attribute_name, $attribute_value ) ) {
$cart->remove_cart_item( $cart_item_key );
$removed = true;
}
}
if ( $removed ) {
wc_add_notice( 'Из корзины были удалены товары с атрибутом "Распродажа".', 'error' );
}
}Проверка результата после внедрения
- Добавьте в каталог товар с нужным атрибутом (например,
pa_sostoyanie=rasprodazha). - Попробуйте добавить этот товар в корзину.
- После обновления корзины товар должен автоматически удалиться, а пользователь увидит сообщение об удалении.
- Товары без указанного атрибута остаются в корзине без изменений.
Включите режим отладки WooCommerce, чтобы убедиться, что хук вызывается и ошибок нет.
Частые ошибки и как исправить
- Неправильный slug атрибута: В WooCommerce для глобальных атрибутов используется prefix
pa_. Проверьте slug атрибута в админке (Товары → Атрибуты). - Атрибут не глобальный, а пользовательский: В этом случае атрибуты могут храниться иначе, и их нужно получать из мета полей товара или варианта.
- Удаление товаров с вариациями: Если в корзине вариации, проверяйте атрибуты вариации, а не родительского товара.
- Сообщение не выводится: Убедитесь, что функция
wc_add_noticeвызывается в правильном месте и что шаблон корзины поддерживает вывод уведомлений.
Практические советы по безопасности и производительности
- Вызывайте функцию удаления только на фронтенде, чтобы не влиять на админ-панель и AJAX-запросы без необходимости.
- Кэширование: При активных плагинах кэширования убедитесь, что корзина обновляется корректно и сообщения выводятся сразу.
- Логирование: Для отладки добавьте временный лог в файл, чтобы отслеживать срабатывание удаления.
- Улучшение UX: Можно добавить JavaScript-уведомления и блокировать кнопку оформления заказа, если в корзине остаются запрещённые товары.
Сравнение вариантов реализации удаления товаров по атрибутам
| Метод | Плюсы | Минусы | Применимость |
|---|---|---|---|
PHP-хук woocommerce_before_calculate_totals | Полный контроль, сразу удаляет товары при обновлении корзины | Нельзя предотвратить добавление товара, только удалять после | Подходит для большинства случаев |
Валидация при добавлении в корзину (woocommerce_add_to_cart_validation) | Предотвращает добавление нежелательных товаров | Сложнее проверять уже добавленные товары, требуется дополнительная логика | Если нужно блокировать добавление заранее |
| JavaScript на фронтенде | Быстрая реакция, можно предупредить пользователя | Можно отключить, не защищает сервер | Для улучшения UX, но не как основное решение |