WooCommerce: автоматическое изменение цены при покупке набора товаров через код

Диагностика задачи: зачем нужна автоматизация изменения цены на набор товаров в WooCommerce

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

Реализовать это можно как через плагины, так и через кастомный код. В этой статье разберём практический пример решения через код, чтобы избежать лишних плагинов и сохранить контроль над логикой.

Пошаговое решение: как автоматически менять цену на набор товаров в WooCommerce с помощью кода

1. Определяем набор товаров и условие для скидки

Для примера предположим, что скидка нужна, если в корзине присутствуют товары с ID 12, 34 и 56 одновременно — это и будет наш набор.

2. Добавляем фильтр на изменение цены в корзине

Используем хук woocommerce_before_calculate_totals, чтобы проверить наличие набора и изменить цену соответствующих товаров.

add_action('woocommerce_before_calculate_totals', 'custom_bundle_price_adjustment', 10, 1);
function custom_bundle_price_adjustment( $cart ) {
    if ( is_admin() && ! defined('DOING_AJAX') ) return;

    // IDs товаров в наборе
    $bundle_ids = array(12, 34, 56);
    $found_ids = array();

    // Проверяем, есть ли все товары набора в корзине
    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        if ( in_array($cart_item['product_id'], $bundle_ids) ) {
            $found_ids[] = $cart_item['product_id'];
        }
    }

    if ( count(array_unique($found_ids)) === count($bundle_ids) ) {
        // Все товары набора есть - применяем скидку 20% на каждый из них
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
            if ( in_array($cart_item['product_id'], $bundle_ids) ) {
                $original_price = $cart_item['data']->get_regular_price();
                $discounted_price = $original_price * 0.8; // 20% скидка
                $cart_item['data']->set_price($discounted_price);
            }
        }
    } else {
        // Если набор не полный - возвращаем оригинальные цены
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
            if ( in_array($cart_item['product_id'], $bundle_ids) ) {
                $cart_item['data']->set_price( $cart_item['data']->get_regular_price() );
            }
        }
    }
}

3. Добавляем уведомление для пользователя о применённой скидке

Чтобы покупатель видел, что скидка сработала, можно добавить сообщение в корзину и на страницу оплаты.

add_action('woocommerce_before_cart', 'custom_bundle_discount_notice');
add_action('woocommerce_before_checkout_form', 'custom_bundle_discount_notice');
function custom_bundle_discount_notice() {
    $bundle_ids = array(12, 34, 56);
    $found_ids = array();

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( in_array($cart_item['product_id'], $bundle_ids) ) {
            $found_ids[] = $cart_item['product_id'];
        }
    }

    if ( count(array_unique($found_ids)) === count($bundle_ids) ) {
        wc_print_notice('Скидка 20% на набор товаров применена!', 'success');
    }
}

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

  • Добавьте в корзину товары с ID 12, 34 и 56. Убедитесь, что цена каждого товара в наборе изменилась на 20% ниже обычной.
  • Проверьте, отображается ли уведомление о скидке на страницах корзины и оформления заказа.
  • Удалите хотя бы один товар из набора и убедитесь, что цены возвращаются к стандартным, а уведомление пропадает.

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

  • Цены не меняются в корзине: Проверьте, правильно ли подключён хук woocommerce_before_calculate_totals. Убедитесь, что условие не блокируется условием is_admin() или другими проверками.
  • Скидка применяется некорректно: Возможно, в корзине дублируются товары, и условие подсчёта не работает. Используйте array_unique() для проверки уникальных ID.
  • Уведомление не отображается: Проверьте, что функция для вывода уведомлений подключена к нужным хукам и что нет конфликтов с другими плагинами, которые могут перехватывать уведомления.
  • Цена не возвращается к оригинальной: Убедитесь, что в else-блоке вы явно устанавливаете цену через set_price() с оригинальным значением.

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

  • Используйте кеширование, если логика пересчитывается часто — например, сохраняйте состояние наличия набора в сессии пользователя.
  • Не храните цены в пользовательских метаполях для изменений — используйте стандартный метод set_price(), чтобы избежать конфликтов с другими функциями WooCommerce.
  • Для сложных наборов или вариативных товаров лучше использовать специализированные плагины-бандлы с поддержкой всех сценариев.
  • Тестируйте изменения на стейджинг-сервере, чтобы избежать сбоев в процессе оформления заказа.

Сравнение вариантов решения задачи

ВариантПлюсыМинусы
Код на хуках WooCommerceГибкость, контроль, нет лишних плагиновТребует знаний PHP, сложнее поддерживать при расширении
Плагин для бандлов (например, WooCommerce Product Bundles)Много функционала, удобный интерфейсДополнительная нагрузка, платные версии, меньше кастомизации
Использование купонов с условиямиПростота настройки без кодаОграниченное применение, нет динамической логики
WooCommerce: как автоматически изменять статус заказа при оплате через код
10.06.2026
WooCommerce: автоматическое отключение платежных методов при отказанном заказе
16.06.2026
WooCommerce: автоматическое изменение цены при покупке набора товаров через код
09.05.2026
Создать и использовать динамические корзинные элементы в WooCommerce с AJAX
17.02.2026
WooCommerce: как изменить статус заказа через хуки и проверить работу
01.05.2026