Диагностика проблемы: почему нужно менять цену товара в корзине программно
В стандартном WooCommerce цена товара в корзине фиксируется на основе данных из базы и не меняется динамически. Но часто требуется изменить стоимость товаров в корзине по разным причинам: скидки, персональные наценки, динамическое ценообразование, акции, или интеграция с внешними системами. Если стандартных купонов и правил недостаточно, приходится использовать фильтры WooCommerce для программной корректировки цены.
Обзор ключевых фильтров для изменения цены в WooCommerce
Основные хуки, которые влияют на цену товара в корзине:
woocommerce_before_calculate_totals— позволяет изменить цену товара до пересчёта итогов корзины;woocommerce_cart_item_price— фильтр для вывода цены товара в корзине;woocommerce_get_price— применяется при получении цены товара (используется в разных местах);woocommerce_cart_item_subtotal— позволяет изменить итоговую стоимость позиции в корзине.
Почему лучше использовать woocommerce_before_calculate_totals
Этот фильтр запускается непосредственно перед пересчётом итоговой суммы корзины. В нём можно менять цену товара динамически, и изменения будут учтены в общей стоимости заказа.
Пошаговое решение: изменение цены товара в корзине
Пример: применим скидку 10% на все товары категории "Распродажа".
add_action('woocommerce_before_calculate_totals', 'custom_discount_on_sale_category', 20, 1);function custom_discount_on_sale_category( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { $product = $cart_item['data']; if ( has_term( 'sale', 'product_cat', $product->get_id() ) ) { $original_price = $product->get_regular_price(); $discounted_price = $original_price * 0.9; // скидка 10% $product->set_price( $discounted_price ); } }}Этот код применяет скидку к товарам категории "sale" в корзине. Обратите внимание, что мы изменяем цену именно в объекте товара в корзине, чтобы корректно обновить итог.
Как проверить, что изменение цены сработало
- Добавьте в корзину товар из категории "sale";
- Перейдите в корзину и проверьте цену товара — она должна быть на 10% ниже обычной;
- Обновите страницу, чтобы убедиться, что скидка применяется стабильно;
- Убедитесь, что итоговая сумма заказа пересчитана корректно.
Расширенный пример: добавление наценки для определённой роли пользователя
Если нужно добавить 15% наценку для роли "оптовик" на все товары, используйте такой код:
add_action('woocommerce_before_calculate_totals', 'add_markup_for_wholesale_role', 20, 1);function add_markup_for_wholesale_role( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; $user = wp_get_current_user(); if ( in_array( 'wholesale', (array) $user->roles ) ) { foreach ( $cart->get_cart() as $cart_item ) { $product = $cart_item['data']; $base_price = $product->get_regular_price(); $new_price = $base_price * 1.15; // +15% $product->set_price( $new_price ); } }}Частые ошибки и как их исправить
- Изменения не применяются или сбрасываются после обновления корзины.
Причина: установка цены внеwoocommerce_before_calculate_totalsили несколько вызовов этого хука.
Решение: убедитесь, что код находится именно в этом хуке и добавьте проверкуdid_action, чтобы избежать повторных изменений. - Изменение цены влияет на все страницы сайта.
Причина: изменение цены объекта товара глобально.
Решение: меняйте цену только в объекте корзины, а не сам товар в базе данных. - Проблемы с кешированием страницы корзины.
Причина: кеширование сервером или плагином.
Решение: отключите кеширование для страниц корзины и оформления заказа.
Практические советы по производительности и безопасности
- Не используйте тяжелые запросы в цикле изменения цены — кэшируйте данные, если надо;
- Проверяйте роль пользователя и другие условия до цикла, чтобы минимизировать нагрузки;
- Не меняйте цену товара в объекте
WC_Productвне корзины, чтобы избежать некорректных данных; - Избегайте конфликтов с другими плагинами, использующими те же фильтры, через приоритеты хука;
- Тестируйте на staging-сайте, чтобы не нарушить процесс оформления заказа.
Сравнение методов изменения цены в корзине
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
Изменение цены в woocommerce_before_calculate_totals | Надёжно, учитывается в итогах, гибко | Требует правильной логики, может конфликтовать | Динамическое изменение цены в корзине |
Фильтр woocommerce_get_price | Меняет цену глобально для вывода | Не подходит для динамических скидок в корзине | Изменение цены на сайте в целом |
| Использование купонов WooCommerce | Простое решение, без кода | Ограничено возможностями купона | Стандартные скидки и акции |