Исключение товаров из корзины WooCommerce по атрибутам (цвет, размер)

Диагностика задачи: зачем исключать товары из корзины по атрибутам

В интернет-магазинах на 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)Удаляет запрещённые товары из корзины сразуУпрощает процесс, не требует действий пользователяМожет вызвать путаницу, если пользователь не заметит удаление

Возникли задачи по WP? Вы можете задать свой вопрос на FAQwp.com Либо обратиться к специалистам поддержки.