Диагностика задачи: зачем нужна автоматизация изменения цены на набор товаров в 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) | Много функционала, удобный интерфейс | Дополнительная нагрузка, платные версии, меньше кастомизации |
| Использование купонов с условиями | Простота настройки без кода | Ограниченное применение, нет динамической логики |