Диагностика задачи: зачем исключать товары из корзины по атрибутам
В интернет-магазинах на WooCommerce иногда возникает необходимость не допускать к оформлению заказа товары с определёнными атрибутами, например, определённого цвета или размера. Это может быть связано с ограничениями поставщика, акциями или логистикой. Стандартного способа в WooCommerce для фильтрации корзины по атрибутам нет, поэтому приходится реализовывать логику через код.
Как получить данные атрибутов товара в корзине
Атрибуты хранятся в метаданных товаров и вариаций. В корзине нам доступны объекты WC_Cart_Item, у которых есть ID товара и вариации. Чтобы получить атрибуты, нужно обратиться к объекту продукта:
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
// $attributes - массив атрибутовДля вариативных товаров лучше обращаться к метаданным вариации:
$variation_id = $cart_item['variation_id'];
if ( $variation_id ) {
$variation = wc_get_product( $variation_id );
$variation_attributes = $variation->get_variation_attributes();
}Пошаговое решение: исключаем товары из корзины по атрибутам
1. Определяем условие фильтрации
Например, исключить из корзины все товары, у которых атрибут pa_color равен red или атрибут pa_size равен xl.
2. Используем хук woocommerce_check_cart_items для проверки корзины перед чекаутом
Этот хук выполняется до оформления заказа, где можно вывести ошибку и запретить покупку.
add_action( 'woocommerce_check_cart_items', 'exclude_products_by_attributes' );
function exclude_products_by_attributes() {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$variation_id = $cart_item['variation_id'];
$attributes = [];
if ( $variation_id ) {
$variation = wc_get_product( $variation_id );
$attributes = $variation->get_variation_attributes();
} else {
$attributes = $product->get_attributes();
}
// Проверяем атрибуты
if ( ( isset( $attributes['pa_color'] ) && $attributes['pa_color'] === 'red' ) ||
( isset( $attributes['pa_size'] ) && $attributes['pa_size'] === 'xl' ) ) {
wc_add_notice( sprintf(
'Товар "%s" с запрещённым атрибутом не может быть приобретён.',
$product->get_name()
), 'error' );
}
}
}3. Альтернатива — автоматически удалять такие товары из корзины
add_action( 'woocommerce_before_calculate_totals', 'remove_products_by_attributes_from_cart' );
function remove_products_by_attributes_from_cart() {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$variation_id = $cart_item['variation_id'];
$attributes = [];
if ( $variation_id ) {
$variation = wc_get_product( $variation_id );
$attributes = $variation->get_variation_attributes();
} else {
$attributes = $product->get_attributes();
}
if ( ( isset( $attributes['pa_color'] ) && $attributes['pa_color'] === 'red' ) ||
( isset( $attributes['pa_size'] ) && $attributes['pa_size'] === 'xl' ) ) {
WC()->cart->remove_cart_item( $cart_item_key );
wc_add_notice( sprintf(
'Товар "%s" был удалён из корзины по причине запрещённого атрибута.',
$product->get_name()
), 'notice' );
}
}
}Проверка результата после внедрения
Чтобы убедиться, что решение работает, выполните следующие шаги:
- Добавьте в корзину товар с запрещённым атрибутом (цвет
redили размерxl). - Перейдите к оформлению заказа. Если используется первый вариант, должна появиться ошибка и оформление будет заблокировано.
- Если второй вариант, товар автоматически удалится из корзины и будет показано уведомление.
- Добавьте товар с разрешёнными атрибутами — он должен успешно добавиться и пройти оформление.
Частые ошибки и как их исправить
- Неправильный ключ атрибута. Атрибуты в WooCommerce имеют префикс
pa_, его нельзя пропускать. Проверьте в админке, как именно называется атрибут (slug). - Проверка атрибутов вариаций не работает. Для вариативных товаров нужно проверять именно вариацию, а не родительский товар. Используйте
get_variation_attributes(). - Товары не удаляются из корзины. Функция удаления из корзины должна вызываться до подсчёта итогов, например, в
woocommerce_before_calculate_totals. Вызов в другом хуке может быть слишком поздним. - Сообщения об ошибках не показываются. Убедитесь, что вызов
wc_add_notice()происходит в правильном хуке (например,woocommerce_check_cart_items), и шаблон темы выводит уведомления.
Практические советы по оптимизации и безопасности
- Не храните жестко список запрещённых атрибутов в коде — вынесите их в настройки темы или отдельный файл для удобства и безопасности.
- Для больших магазинов с множеством атрибутов оптимизируйте цикл проверки — например, используйте кэширование или фильтры для предварительной выборки.
- Тестируйте на staging-сервере, чтобы не сломать процесс покупки на живом сайте.
- Проверяйте совместимость с плагинами кеширования и оптимизации, чтобы уведомления wc_add_notice отображались корректно.
Сравнение вариантов решения задачи
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
Запретить оформление с ошибкой (woocommerce_check_cart_items) | Показывает ошибку при попытке оформить заказ с запрещённым товаром | Пользователь видит причину и может изменить корзину | Не удаляет товар автоматически, требует действий пользователя |
Автоматическое удаление товара (woocommerce_before_calculate_totals) | Удаляет запрещённые товары из корзины сразу | Упрощает процесс, не требует действий пользователя | Может вызвать путаницу, если пользователь не заметит удаление |