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 с применением AJAX
28.01.2026
Как изменить регистр текста в WordPress автоматически
02.03.2026
Как отключить автовоспроизведение видео в блоках Gutenberg WordPress
11.02.2026
Как автоматизировать очистку кеша в WordPress
16.03.2026
Как запретить отображение изображений в WordPress для защиты от копирования
13.03.2026