WooCommerce: как исключить определённые товары из автоматических скидок

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

В типичных интернет-магазинах на WooCommerce часто возникает ситуация, когда необходимо применить автоматические скидки ко всем товарам, кроме определённой группы или отдельных продуктов. Например, это могут быть новинки, товары по специальным ценам, бренды с ограниченными акциями или товары из определённых категорий. Без фильтрации таких товаров скидка будет уменьшать их стоимость, что может привести к убыткам или конфликтам с поставщиками.

Чтобы решить эту задачу, важно понять, как WooCommerce применяет скидки и где можно вмешаться программно для исключения товаров.

Как работают автоматические скидки в WooCommerce

Автоматические скидки чаще всего реализуются через купоны с автоматическим применением или через плагины, которые применяют скидки по определённым правилам. В любом случае WooCommerce вычисляет итоговую стоимость корзины, применяя фильтры и хуки, например woocommerce_cart_calculate_fees или woocommerce_before_calculate_totals.

Для исключения товаров из скидок нужно перехватить момент расчёта цены и изменить стоимость товаров, к которым скидка не должна применяться.

Пошаговое решение: исключаем товары из автоматических скидок через хук woocommerce_before_calculate_totals

1. Определяем критерии исключения

Это могут быть ID товаров, ID категорий, теги или мета-поля. В примере ниже исключим товары по ID.

2. Добавляем кастомный код в файл functions.php вашей активной темы или в плагин для кастомных функций

add_action('woocommerce_before_calculate_totals', 'exclude_products_from_auto_discount', 20, 1);
function exclude_products_from_auto_discount( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
    
    // Массив ID товаров для исключения из скидок
    $excluded_products = array(12, 34, 56); 

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product_id = $cart_item['product_id'];
        if ( in_array( $product_id, $excluded_products ) ) {
            // Убираем все скидки, установленные ранее
            if ( isset( $cart_item['data'] ) ) {
                $cart_item['data']->set_price( $cart_item['data']->get_regular_price() );
            }
        }
    }
}

3. Объяснение кода

  • На хук woocommerce_before_calculate_totals навешиваем функцию с приоритетом 20, чтобы она сработала после других скидочных обработчиков.
  • В функции проверяем, не админ ли это и не AJAX ли, чтобы избежать лишних вычислений.
  • Создаём массив $excluded_products с ID товаров, которые нужно исключить.
  • Для каждого товара в корзине, если его ID совпадает, устанавливаем цену равной обычной цене без скидок с помощью set_price().

Проверка результата после внедрения

1. Добавьте в корзину несколько товаров, включая те, что в массиве $excluded_products.

2. Проверьте, что скидка применяется ко всем товарам, кроме исключённых.

3. Для отладки можно временно добавить error_log в функцию, чтобы убедиться, что она срабатывает и меняет цены:

error_log('Обрабатывается товар ID: ' . $product_id);

4. Очистите кэш сайта и браузера.

Частые ошибки и как их исправить

  • Скидка не применяется к остальным товарам: Возможно, приоритет хука слишком низкий, попробуйте увеличить приоритет до 30 или 40.
  • Цена исключённых товаров не сбрасывается: Проверьте, что в корзине действительно те ID, что указаны в массиве, и что вы вызываете set_price() для объекта товара.
  • Изменения не видны в админке или при AJAX-запросах: Убедитесь, что проверка is_admin() && ! defined('DOING_AJAX') корректно исключает ненужные вызовы, возможно, временно отключите для отладки.
  • Проблемы с совместимостью плагинов скидок: Некоторые плагины могут переопределять цены позже, изучите их документацию и логику применения скидок.

Практические советы по производительности и безопасности

  • Не храните массив исключённых товаров в коде, если их много — лучше использовать мета-поля или отдельную категорию для динамического определения.
  • Избегайте выполнения кода при админских запросах и AJAX, не относящихся к фронтенду корзины.
  • Тестируйте на копии сайта перед внедрением в продакшен.
  • Если используете плагины кеширования, обязательно очищайте кеш после внесения изменений.

Альтернативные варианты реализации

ВариантПлюсыМинусы
Через хук woocommerce_before_calculate_totalsГибко, программируемо, не требует плагиновТребует навыков PHP, возможны конфликты
Использование плагинов скидок с фильтрами исключенийУдобный интерфейс, поддержка сложных правилМожно платить за премиум, меньше контроля
Добавление мета-полей и условий в шаблоныЛегко для небольших правокМожет приводить к дублированию логики
Как использовать AJAX в WordPress для объявлений без перезагрузки страницы
03.02.2026
Как использовать хук pre_get_posts для гибкой фильтрации запросов в WordPress
13.12.2025
WooCommerce: как исключить товары со скидкой из способов оплаты
30.04.2026
Как создать нетипичный файловый хендлер в WordPress для обработки нестандартных типов файлов
24.03.2026
WooCommerce: как исключить определённые товары из применения скидок
07.05.2026