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

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

WooCommerce предоставляет стандартные возможности для создания скидок через купоны и правила в корзине, однако в некоторых случаях требуется более гибкий и автоматизированный механизм изменения цены товара в зависимости от сложных условий. Например, если скидка зависит от нескольких параметров одновременно (категория товара, количество в заказе, роль пользователя) или если нужно динамически менять цену без применения купонов.

В таких ситуациях стандартные методы не позволяют реализовать бизнес-логику без кастомного кода.

Пошаговое решение: как программно менять цену товара в корзине WooCommerce

1. Используем хук woocommerce_before_calculate_totals

Этот хук позволяет изменить цену товара перед расчетом итогов корзины.

add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_discount', 20, 1);
function custom_dynamic_price_discount( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
    
    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product = $cart_item['data'];
        $original_price = $product->get_regular_price();
        $quantity = $cart_item['quantity'];

        // Пример условия: скидка 15% если количество больше 3
        if ( $quantity > 3 ) {
            $new_price = $original_price * 0.85; // 15% скидка
            $product->set_price( $new_price );
        } else {
            // Вернуть исходную цену, если условие не выполнено
            $product->set_price( $original_price );
        }
    }
}

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

Чтобы расширить логику, добавим проверку роли пользователя и категории товара:

add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_discount_extended', 20, 1);
function custom_dynamic_price_discount_extended( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
    
    $user = wp_get_current_user();
    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product = $cart_item['data'];
        $original_price = $product->get_regular_price();
        $quantity = $cart_item['quantity'];

        // Проверяем роль пользователя
        if ( in_array( 'wholesale_customer', (array) $user->roles ) ) {
            // Проверяем категорию товара
            if ( has_term( 'bulk-items', 'product_cat', $product->get_id() ) ) {
                // Устанавливаем скидку 25% если количество больше 10
                if ( $quantity > 10 ) {
                    $product->set_price( $original_price * 0.75 );
                } else {
                    $product->set_price( $original_price );
                }
            }
        }
    }
}

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

  • Добавьте в корзину товары с разным количеством, в том числе свыше пороговых значений (например, больше 3 или 10 штук).
  • Залогиньтесь под разными пользователями с разными ролями (например, розничный покупатель и wholesale_customer).
  • Проверьте, что цены в корзине корректно изменяются согласно логике.
  • Используйте инструменты разработчика браузера для проверки, что цена товара обновляется динамически, и итоговая сумма рассчитывается правильно.

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

  • Цена не меняется в корзине. Проверьте, правильно ли подключен хук woocommerce_before_calculate_totals и не блокирует ли другие плагины изменение цены.
  • Цена сбрасывается после обновления страницы. Убедитесь, что вы не используете кеширование корзины или страниц, где отображается корзина.
  • Цена меняется для всех пользователей. Проверьте корректность проверки роли пользователя. Для теста можно вывести роли через error_log(print_r(wp_get_current_user()->roles, true));.
  • Изменение цены влияет на отображение в админке. Добавьте проверку if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; в функцию, чтобы избежать изменения цены в административной части.

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

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

Сравнение методов реализации изменения цены

МетодПлюсыМинусыКогда использовать
Стандартные купоны WooCommerce Простота использования, нет кода Ограниченная логика, не подходит для сложных условий Простые скидки для всех пользователей или по купону
Правила корзины (WooCommerce Discounts) Больше гибкости, можно комбинировать условия Сложность настройки, нет динамической цены товара Скидка на корзину, но не изменение цены товара
Кастомный код на woocommerce_before_calculate_totals Максимальная гибкость, динамическое изменение цены Требует навыков PHP, риск ошибок Сложные бизнес-правила, автоматизация скидок
Как найти и убрать дубли страниц в WordPress без потери SEO
15.08.2026
Как добавить автоматическое сохранение в формы WordPress для защиты данных
30.08.2026
WooCommerce: как сбросить статус заказа при неудачном платеже
08.08.2026
WooCommerce: автоматическое изменение статуса заказа при отсутствии платежа
02.10.2026
Как отключить индексацию архивов авторов и дат в WordPress без потери нужных страниц
18.08.2026