Диагностика проблемы: зачем исключать товары из корзины по атрибутам
В WooCommerce часто возникает задача запретить покупку или исключить из корзины товары с определёнными атрибутами (например, товары с пометкой "Распродажа", "Пробный образец" или товары, не подлежащие продаже через корзину). Это может понадобиться для соблюдения бизнес-правил, предотвращения конфликтов в заказах или управления ассортиментом.
Без специальной доработки WooCommerce не предоставляет встроенных средств для динамического исключения товаров из корзины на основе атрибутов. В результате такие товары остаются в корзине, что может привести к ошибкам оформления заказа, конфликтам с логистикой или неверной аналитике.
Пошаговое решение: исключение товаров из корзины по атрибутам через код
1. Определение атрибутов для исключения
Сначала определите, какие именно атрибуты будут служить фильтром. Например, допустим, у вас есть атрибут pa_sale_status с терминами: regular, clearance, sample. Нужно исключить из корзины товары с атрибутом pa_sale_status=sample.
2. Добавление фильтра в functions.php или через плагин
Используем хук woocommerce_check_cart_items для проверки корзины перед оформлением заказа и удаления товаров с нужным атрибутом. Пример кода:
add_action('woocommerce_check_cart_items', 'exclude_products_by_attribute_from_cart');
function exclude_products_by_attribute_from_cart() {
// Атрибут и значение, по которым исключаем товары
$attribute_name = 'pa_sale_status';
$excluded_term_slug = 'sample';
// Получаем корзину
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$product_id = $product->get_id();
// Получаем термины атрибута у товара
$terms = wp_get_post_terms($product_id, $attribute_name, array('fields' => 'slugs'));
if (in_array($excluded_term_slug, $terms)) {
// Удаляем товар из корзины
WC()->cart->remove_cart_item($cart_item_key);
// Добавляем уведомление для пользователя
wc_add_notice(sprintf('Товар "%s" исключен из корзины, так как не подлежит продаже через корзину.', $product->get_name()), 'error');
}
}
}3. Кэширование и оптимизация
Функция wp_get_post_terms вызывается для каждого товара в корзине, что при большом количестве товаров может влиять на производительность. Для оптимизации можно закешировать результаты в статической переменной:
add_action('woocommerce_check_cart_items', 'exclude_products_by_attribute_from_cart_optimized');
function exclude_products_by_attribute_from_cart_optimized() {
$attribute_name = 'pa_sale_status';
$excluded_term_slug = 'sample';
static $product_terms_cache = [];
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$product_id = $product->get_id();
if (!isset($product_terms_cache[$product_id])) {
$product_terms_cache[$product_id] = wp_get_post_terms($product_id, $attribute_name, array('fields' => 'slugs'));
}
if (in_array($excluded_term_slug, $product_terms_cache[$product_id])) {
WC()->cart->remove_cart_item($cart_item_key);
wc_add_notice(sprintf('Товар "%s" исключен из корзины, так как не подлежит продаже через корзину.', $product->get_name()), 'error');
}
}
}Проверка результата после внедрения
- Добавьте в магазин товар с атрибутом
pa_sale_status=sample. - Добавьте этот товар в корзину вместе с обычным товаром.
- Перейдите в корзину или оформление заказа.
- Убедитесь, что товар с атрибутом
sampleавтоматически удаляется из корзины и появляется уведомление об удалении. - Если товар остался, проверьте логи сервера и логи WooCommerce на наличие ошибок.
Частые ошибки и как их исправить
- Атрибут указан неверно: Убедитесь, что в коде указан правильный slug атрибута, он всегда начинается с
pa_и совпадает со slugом в WooCommerce. - Товары не удаляются, уведомление не появляется: Возможно, конфликт с другим плагином, который перехватывает
woocommerce_check_cart_items. Проверьте деактивацию других плагинов или поместите код в плагин с более высоким приоритетом. - Производительность падает при большом количестве товаров: Используйте кеширование термов, как показано в оптимизированном варианте кода.
- Удаление товара в корзине не обновляется визуально: Проверьте, что корзина перезагружается при изменениях, при необходимости добавьте JavaScript для обновления.
Практические советы по безопасности и производительности
- Не выполняйте запросы к базе данных внутри циклов без кеширования.
- Проверяйте, что пользователь имеет права на просмотр товаров, чтобы избежать утечки информации.
- Для больших магазинов используйте transient API для кэширования результатов запросов к атрибутам.
- Добавляйте уведомления через
wc_add_noticeв пользовательском контексте, не блокируя процесс оформления заказа.
Таблица сравнения вариантов реализации исключения товаров из корзины
| Метод | Преимущества | Недостатки | Применение |
|---|---|---|---|
Код на хуке woocommerce_check_cart_items | Гибкий, не требует плагинов, можно точно настроить | Требует навыков PHP, возможны конфликты с плагинами | Малые и средние магазины с кастомными требованиями |
| Плагины для фильтрации корзины | Простота установки, готовые настройки | Могут быть ограничены в функционале, нагрузка | Быстрое решение без кастомизации |
| Модификация шаблонов WooCommerce | Контроль над отображением, UX | Не исключает товары из корзины, только скрывает | Дополнительный UX, не основное решение |