WooCommerce: решение проблемы неработающей функции динамического изменения цены товара в корзине

Диагностика проблемы с динамическим изменением цены в корзине WooCommerce

Многие разработчики сталкиваются с тем, что функция изменения цены товара в корзине через хук woocommerce_before_calculate_totals не работает: цена не меняется, несмотря на корректный код. Проблема обычно проявляется в следующих ситуациях:

  • Цена товара в корзине остается неизменной при попытке программного переопределения.
  • Изменения цены не отображаются в итогах заказа и на странице оформления.
  • Кэширование или кеширующие плагины мешают обновлению цены.

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

Как проверить, что хук вызывается

Добавьте простой лог или вывод в файл functions.php вашей темы или в плагин:

add_action('woocommerce_before_calculate_totals', function($cart) {
    error_log('Hook woocommerce_before_calculate_totals called');
}, 10);

Если сообщение появляется в debug.log, значит хук срабатывает.

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

Для изменения цены товара в корзине используйте следующий рабочий шаблон кода, который обновляет цену каждого товара динамически:

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

    // Чтобы избежать повторного изменения цены при Ajax-запросах
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product = $cart_item['data'];
        $original_price = $product->get_regular_price();

        // Пример: снижать цену на 10% при количестве товаров больше 3
        if ( $cart_item['quantity'] > 3 ) {
            $new_price = $original_price * 0.9;
            $product->set_price( $new_price );
        } else {
            // Восстановить оригинальную цену если условие не выполняется
            $product->set_price( $original_price );
        }
    }
}

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

  • Проверяем, что код не выполняется в админке и не повторяется несколько раз.
  • Перебираем все товары в корзине через $cart->get_cart().
  • Получаем объект товара и его регулярную цену.
  • Изменяем цену с помощью метода set_price() объекта WC_Product.
  • Обязательно восстанавливаем оригинальную цену, если условие не выполняется, чтобы избежать неправильных цен.

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

Чтобы убедиться, что цена изменилась:

  • Добавьте в корзину товар с количеством более 3 единиц.
  • Обновите страницу корзины и посмотрите на цену — она должна быть на 10% ниже.
  • Проверьте, что при количестве 3 и меньше цена товара соответствует регулярной цене.
  • Проверьте итоговую сумму заказа — она должна пересчитываться корректно.

Если изменения не видны, отключите кеширующие плагины, очистите кэш браузера и серверный кэш.

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

  • Изменение цены без сброса повторных вызовов: цена меняется многократно, что приводит к неправильному результату. Решение — использовать did_action() для ограничения повторного исполнения.
  • Изменение цены не в объекте WC_Product: попытка менять цену через метаданные или нестандартные поля не работает. Используйте метод set_price().
  • Не учитывается AJAX: в некоторых случаях изменения не применяются из-за кеширования AJAX. Проверяйте условие is_admin() && ! defined('DOING_AJAX').
  • Плагины кеширования: отключите или исключите страницы корзины и оформления из кеша.

Практические советы по оптимизации и безопасности

  • Не храните изменённую цену в сессии или метаданных, меняйте только в объекте товара в корзине.
  • Используйте приоритет 20 или выше в хуке, чтобы цена изменилась после всех основных вычислений.
  • Проверяйте логи ошибок и включайте WP_DEBUG для отладки.
  • При масштабных изменениях цен на сайте лучше реализовывать логику через фильтры WooCommerce для скидок и купонов (например, woocommerce_get_price_html и купоны), чтобы избежать конфликтов.

Сравнение способов динамического изменения цены в корзине WooCommerce

МетодОписаниеПреимуществаНедостатки
Хук woocommerce_before_calculate_totals + set_price() Изменение цены объекта товара в корзине Прямой контроль, работает с любыми условиями Требует правильного управления повторным вызовом и кешем
Использование купонов и скидок WooCommerce Создание скидок через стандартный функционал Простота, интеграция с интерфейсом WooCommerce Ограничено условиями, сложно реализовать сложные сценарии
Плагины динамического ценообразования Готовые решения для различных сценариев Быстрое внедрение, поддержка обновлений Потенциальный конфликт с кастомным кодом, затраты
Как удалить ревизии записей в WordPress с помощью плагинов и кода
13.02.2026
WooCommerce: решение проблемы нерабочей функции динамического изменения цены товара при промокодах
31.05.2026
WooCommerce: автоматическое удаление закрытых заказов с помощью WP-Cron
23.05.2026
Как добавить динамические атрибуты в shortcode WordPress
01.03.2026
WooCommerce: как автоматически удалять заказы со статусом Отменен и Возврат
18.06.2026