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

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

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

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

Пошаговое решение: использование хука woocommerce_before_calculate_totals

1. Подключаем функцию к хуку

Хук woocommerce_before_calculate_totals вызывается перед пересчетом итоговой суммы корзины. В этот момент можно изменить цены товаров в корзине, и эти изменения будут учтены во всех расчетах.

2. Пример кода для изменения цены товара на 10% скидку для пользователей с ролью "wholesale_customer"

add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_adjustment', 10, 1);
function custom_dynamic_price_adjustment($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    // Проверяем роль пользователя
    if (!is_user_logged_in()) return;
    $user = wp_get_current_user();
    if (!in_array('wholesale_customer', (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);
    }
}

3. Как добавить надбавку за дополнительную услугу, выбранную в пользовательском поле

Если товары имеют пользовательское метаполе, например _extra_service, и при его наличии нужно добавить 100 рублей к цене:

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

    foreach ($cart->get_cart() as $cart_item) {
        $extra_service = $cart_item['data']->get_meta('_extra_service');
        if ($extra_service) {
            $price = $cart_item['data']->get_price();
            $cart_item['data']->set_price($price + 100);
        }
    }
}

Как проверить, что изменение цены сработало

  • Добавьте в корзину товар, для которого должно применяться динамическое изменение.
  • Если скидка зависит от роли пользователя, войдите под соответствующим аккаунтом.
  • Проверьте итоговую цену в корзине и на странице оформления заказа — цена должна соответствовать измененной.
  • Включите режим отладки WooCommerce и проверьте, что хук срабатывает (через логи или var_dump внутри функции).

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

  • Изменение цены в админке или при AJAX-запросах: функция изменяет цену и в админке, что приводит к ошибкам. Решение — добавлять проверку if (is_admin() && !defined('DOING_AJAX')) return;.
  • Цена меняется только визуально, итог не пересчитывается: это происходит, если менять цену вне хука woocommerce_before_calculate_totals. Всегда используйте этот хук для внесения изменений.
  • Цена сбрасывается после обновления страницы: возможно, цена задается без использования метода set_price() объекта товара в корзине.

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

  • Избегайте тяжелых запросов в функции изменения цены — она вызывается часто и должна быть максимально быстрой.
  • Не сохраняйте изменённые цены в базу — изменения должны действовать только в сессии корзины.
  • Используйте проверку прав доступа, чтобы динамические цены не применялись для неподходящих пользователей.

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

СпособПлюсыМинусы
Хук woocommerce_before_calculate_totalsЧистый, поддерживаемый способ, изменения применяются корректно ко всей логике корзиныТребует аккуратного кода, может влиять на производительность при сложных расчетах
Использование фильтра цены товара woocommerce_product_get_priceМеняет цену глобально, подходит для постоянных скидокСложнее учитывать разные условия для корзины, влияет на всю цену товара везде
Создание дополнительных товаров-надбавок в корзинеПростая логика, легко управлять отдельными позициямиУвеличивает количество позиций в корзине, не меняет цену самого товара
Автоматическое отключение и удаление незавершённых заказов в WooCommerce
22.05.2026
Как успешно обновлять WooCommerce без потери данных
26.04.2026
Как добавить владельца постов в REST API WordPress
14.03.2026
Как удалить верхний padding в WordPress без кода
19.01.2026
Автоматическое удаление незавершённых заказов в WooCommerce
29.04.2026