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

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

В WooCommerce стандартная логика использует цену товара из настроек каталога при добавлении в корзину. Но в ряде случаев требуется динамически менять стоимость — например, при индивидуальных скидках, изменении цены по опциям, или для B2B-решений с кастомной тарификацией. Чтобы правильно реализовать это, важно не менять цену товара в базе, а корректировать стоимость именно на уровне корзины.

Как изменить цену товара в корзине с помощью фильтра woocommerce_before_calculate_totals

Для изменения цены при добавлении товара в корзину используйте хук woocommerce_before_calculate_totals. В этом хук можно перебрать все позиции корзины и задать нужную цену через метод set_price() объекта WC_Cart_Item.

add_action('woocommerce_before_calculate_totals', 'custom_change_cart_item_price', 20, 1); 
function custom_change_cart_item_price($cart) {
    if (is_admin() && !defined('DOING_AJAX')) {
        return;
    }
    foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
        // Пример: меняем цену для товара с ID 123
        if ($cart_item['product_id'] == 123) {
            $new_price = 50; // новая цена в вашей валюте
            $cart_item['data']->set_price($new_price);
        }
    }
}

Этот код не меняет цену в базе, а только отображает новую стоимость в корзине и на страницах оформления заказа.

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

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

add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_based_on_meta', 20, 1);
function custom_dynamic_price_based_on_meta($cart) {
    if (is_admin() && !defined('DOING_AJAX')) {
        return;
    }
    foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
        $product = $cart_item['data'];
        $base_price = $product->get_regular_price();
        $extra_fee = (float) get_post_meta($product->get_id(), '_extra_fee', true);
        if ($extra_fee > 0) {
            $new_price = $base_price + $extra_fee;
            $product->set_price($new_price);
        }
    }
}

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

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

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

  • Цена не меняется в корзине: убедитесь, что ваш код подключён и что хук woocommerce_before_calculate_totals имеет приоритет не ниже 10. Также проверьте, что цена меняется на объекте продукта через set_price(), а не на массиве.
  • Изменения применяются и в админке, ломая данные: добавьте проверку is_admin() && !defined('DOING_AJAX'), чтобы не менять цену при работе в админке.
  • Цена сбрасывается после обновления корзины: убедитесь, что изменение цены происходит при каждом вызове woocommerce_before_calculate_totals, а не только при первом добавлении товара.

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

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

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

МетодОписаниеПреимуществаНедостатки
Изменение цены в базе (через update_post_meta)Прямое обновление цены товара в базе данныхПостоянное изменение ценыНарушает логику WooCommerce, влияет на все заказы, опасно
Фильтр woocommerce_before_calculate_totalsДинамическая смена цены на уровне корзиныБезопасно, локально для конкретного заказа, гибкоНужно писать код, не влияет на уже сделанные заказы
Плагины для динамического ценообразованияИспользование готовых решенийУдобно, поддержка, множество функцийМожет быть дорого, не всегда подходит под кастомные задачи

Сервис определения шаблона и плагинов на сайте