Как использовать хук WooCommerce woocommerce_before_calculate_totals для изменения цен в корзине

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

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

Как работает хук woocommerce_before_calculate_totals

Хук вызывается до того, как WooCommerce пересчитывает итоговую стоимость корзины и каждого её элемента. В него передаётся объект корзины (WC_Cart), где можно получить все элементы корзины и изменить их цену с помощью метода set_price() у объекта WC_Cart_Item.

Пример базового использования хука:

add_action('woocommerce_before_calculate_totals', 'custom_change_price_in_cart', 10, 1);
function custom_change_price_in_cart($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return; // Защита от админки
    foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
        // Новая цена
        $new_price = 1000; // Например фиксированная цена
        $cart_item['data']->set_price($new_price);
    }
}

Пошаговое решение: динамическая корректировка цены с проверкой

Рассмотрим более практичный пример: скидка 10% для пользователей с ролью "оптовик" на все товары в корзине.

  1. Добавляем проверку роли пользователя.
  2. Проходим по каждому товару в корзине.
  3. Вычисляем новую цену с учётом скидки.
  4. Устанавливаем новую цену через set_price().
add_action('woocommerce_before_calculate_totals', 'apply_wholesale_discount', 10, 1);
function apply_wholesale_discount($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    // Проверяем роль пользователя
    if (!is_user_logged_in()) return;
    $user = wp_get_current_user();
    if (!in_array('wholesaler', (array) $user->roles)) return;

    foreach ($cart->get_cart() as $cart_item) {
        $original_price = $cart_item['data']->get_regular_price();
        $discounted_price = $original_price * 0.9; // 10% скидка
        $cart_item['data']->set_price($discounted_price);
    }
}

Как проверить, что код работает

  • Залогиньтесь под пользователем с ролью wholesaler (создайте её, если нужно).
  • Добавьте товар в корзину.
  • Перейдите в корзину и проверьте, что цена товара уменьшилась на 10% от регулярной.
  • Если сменить пользователя на другого с другой ролью — цена не меняется.

Частые ошибки при использовании woocommerce_before_calculate_totals

  • Изменение цены без проверки контекста. Например, изменение цены в админке или при AJAX-запросах может привести к ошибкам. Используйте проверку is_admin() и DOING_AJAX.
  • Использование неправильных методов для установки цены. Нужно менять цену через $cart_item['data']->set_price(), а не напрямую менять значения в массиве.
  • Отсутствие проверки роли или условий. Это может привести к изменению цены для всех пользователей.
  • Кэширование. Если используются плагины кеширования, изменения в корзине могут не отображаться сразу.

Дополнительные практические советы

Обработка множества условий и скидок

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

Производительность

Избегайте тяжелых запросов в функции, которая вызывается на каждый пересчет корзины. Кэшируйте результаты и минимизируйте вызовы API.

Безопасность

Не доверяйте пользовательским данным без проверки. Все вычисления делайте на стороне сервера.

Таблица сравнения способов изменения цены в WooCommerce

МетодПримерПреимуществаНедостатки
Хук woocommerce_before_calculate_totalsset_price() в корзинеДинамическая корректировка без изменения базыПрименяется только в корзине/чекауте
Изменение цены товара в базеupdate_post_meta с _priceПостоянное изменение ценыРиски сломать магазин, влияет на все заказы
Создание купоновАвтоматические скидки WooCommerceПростота использования для конечного пользователяМеньшая гибкость для сложной логики
Как избежать конфликтов методов в WooCommerce: практическое руководство
21.04.2026
Как сделать автоматический редирект после входа в WordPress
12.01.2026
Использование хука pre_get_posts для кастомной фильтрации товаров WooCommerce
25.04.2026
Как создать автоматический отчет в WordPress с помощью WP-Cron и REST API
28.03.2026
Как создать настройки плагина WordPress на основе Customizer
11.04.2026