Диагностика задачи: зачем исключать товары по атрибутам из корзины
В WooCommerce часто возникает необходимость исключить из корзины товары с определёнными атрибутами — например, товары с пометкой "скидка не распространяется" или товары, не участвующие в акции. Это нельзя решить стандартными настройками, поэтому приходится вмешиваться программно.
Типичная ошибка — попытка убрать товар из корзины по ID, что неудобно при большом ассортименте с динамическими атрибутами. Правильнее работать именно с атрибутами, чтобы решение было универсальным.
Как проверить наличие нужных атрибутов у товаров в корзине
В WooCommerce атрибуты хранятся в объекте товара WC_Product. Их можно получить через метод get_attributes(). В корзине нужно пройтись по всем элементам и проверить атрибуты товара.
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
// $attributes - массив WC_Product_Attribute объектов
}Пример: как вывести все атрибуты товара в корзине
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
foreach ( $attributes as $attribute ) {
// Получаем имя атрибута
$name = $attribute->get_name();
// Получаем значения атрибута (массив или строка)
$options = $attribute->get_options();
error_log('Атрибут: ' . $name . '; Значения: ' . implode(', ', $options));
}
}Пошаговое решение: исключение товаров с заданным атрибутом из корзины
Допустим, нужно исключить все товары с атрибутом pa_sale и значением no. Это значит, что товары с этим атрибутом не должны попадать в корзину.
Шаг 1. Создаём фильтр на добавление товара в корзину
add_filter('woocommerce_add_to_cart_validation', 'exclude_products_by_attribute', 10, 3);
function exclude_products_by_attribute($passed, $product_id, $quantity) {
$product = wc_get_product($product_id);
if ( ! $product ) {
return $passed;
}
$attributes = $product->get_attributes();
// Проверяем наличие нужного атрибута
if ( isset($attributes['pa_sale']) ) {
$attribute = $attributes['pa_sale'];
$options = $attribute->get_options();
// Если значение "no" найдено, блокируем добавление
if ( in_array('no', $options) ) {
wc_add_notice('Этот товар нельзя добавить в корзину.', 'error');
return false;
}
}
return $passed;
}Шаг 2. Удаляем товары с этим атрибутом из уже добавленных (например, при обновлении корзины)
add_action('woocommerce_check_cart_items', 'remove_products_by_attribute_from_cart');
function remove_products_by_attribute_from_cart() {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
if ( isset($attributes['pa_sale']) ) {
$attribute = $attributes['pa_sale'];
$options = $attribute->get_options();
if ( in_array('no', $options) ) {
WC()->cart->remove_cart_item($cart_item_key);
wc_add_notice('Товар "' . $product->get_name() . '" удалён из корзины, так как не может быть куплен.', 'notice');
}
}
}
}Проверка результата
- Попробуйте добавить в корзину товар с атрибутом
pa_sale=no. Добавление должно быть заблокировано с сообщением об ошибке. - Если товар уже в корзине, обновите корзину — товар должен автоматически удалиться с уведомлением.
- Проверьте через
error_logили отладчик, что фильтр срабатывает именно на нужных товарах.
Частые ошибки и их исправление
- Ошибка: Атрибуты не проверяются, потому что используете slug атрибута без префикса
pa_.
Решение: WooCommerce добавляет префиксpa_для пользовательских атрибутов. Обязательно используйте его. - Ошибка: Значения атрибута не совпадают, т.к. сравниваете с неправильным регистром или форматом.
Решение: Проверяйте черезerror_logреальные значения из$attribute->get_options()— они всегда в нижнем регистре и без пробелов. - Ошибка: Товар с атрибутом удаляется, но страница корзины не обновляется.
Решение: После удаления используйте принудительное обновление корзины или AJAX, если корзина динамическая.
Практические советы по безопасности и производительности
- Не используйте запросы к базе напрямую для проверки атрибутов — это замедляет работу. Используйте объектные методы WooCommerce.
- Фильтр
woocommerce_add_to_cart_validationсрабатывает быстро, поэтому лучше проверять атрибуты именно там, чтобы не добавлять лишние товары в корзину. - Если атрибутов много, кэшируйте результаты проверки в сессии или transient, чтобы не делать повторные вызовы.
- Добавляйте пользовательские сообщения через
wc_add_notice, чтобы пользователь понимал причину блокировки товара.
Сравнение способов исключения товаров из корзины
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
Фильтр woocommerce_add_to_cart_validation |
Блокировка добавления товара сразу | Лёгкий, предотвращает попадание товара в корзину | Не удаляет товар, добавленный ранее |
Хук woocommerce_check_cart_items |
Удаление товаров уже в корзине | Работает при обновлении корзины, гарантирует чистоту корзины | Может вызвать неудобства из-за внезапного удаления товара |
| JS-валидация в фронтенде | Блокировка на клиенте | Быстрая реакция, удобство для пользователя | Можно обойти, не безопасно |