Диагностика задачи: зачем менять цену товара программно
Часто требуется динамически менять цену товара в WooCommerce без ручного редактирования в админке: например, при изменении количества товара в заказе, по специальным условиям акции, или для применения скидок по сложным правилам. Решение через хуки WooCommerce позволяет автоматизировать эти сценарии, экономя время и исключая ошибки.
Обзор ключевых хуков WooCommerce для изменения стоимости товара
Для изменения цены товаров в корзине или заказе актуальны следующие хуки:
woocommerce_before_calculate_totals— применяется перед расчетом итоговой стоимости в корзине. Позволяет динамически изменить цену товара в объектеWC_Cart_Item.woocommerce_get_price— фильтр для изменения базовой цены товара при выводе.woocommerce_order_item_get_total— фильтр для изменения стоимости товара уже в заказе.
Для автоматизации расчетов лучше использовать woocommerce_before_calculate_totals в корзине, чтобы корректно пересчитать итог.
Пошаговое решение: динамическое изменение цены товара в корзине
Рассмотрим пример, где цена товара уменьшается на 10%, если в корзине больше 3 единиц товара:
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_adjustment', 20, 1);function custom_dynamic_price_adjustment( $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 ) { if ( $cart_item['quantity'] > 3 ) { $original_price = $cart_item['data']->get_regular_price(); $discounted_price = $original_price * 0.9; // скидка 10% $cart_item['data']->set_price( $discounted_price ); } }}Этот код в функции хука проверяет количество товара и снижает цену, корректно обновляя итог корзины.
Проверка результата после внедрения
- Добавьте в корзину товар с количеством больше 3.
- Обновите корзину, убедитесь, что цена товара изменилась на 10% меньше.
- Проверьте общую сумму заказа и убедитесь, что она соответствует обновленным ценам.
- Для проверки используйте консоль браузера или плагин Query Monitor для отслеживания хука.
Частые ошибки и как их исправить
- Изменение цены в админке или при AJAX-запросах не работает: добавьте проверку
is_admin() && ! defined('DOING_AJAX')чтобы исключить выполнение в админке. - Несколько срабатываний одного хука приводят к неправильной цене: используйте
did_action()для ограничения повторного вызова. - Цена меняется, но итог заказа не пересчитывается: убедитесь, что изменение происходит в
woocommerce_before_calculate_totals, а не после подсчета. - Изменение цены влияет на все товары, а не на нужные: уточняйте условие внутри цикла, например, по ID или количеству.
Практические советы по безопасности и производительности
- Не храните изменённые цены в базе данных напрямую — изменяйте цену только на лету в корзине.
- Избегайте тяжелых вычислений в хуках, чтобы не замедлять работу сайта.
- Проверяйте совместимость с другими плагинами, которые могут влиять на цены.
- Для сложных правил скидок лучше использовать отдельные плагины или собственные классы, чтобы код был поддерживаемым.
Таблица сравнения способов изменения цены в WooCommerce
| Метод | Где применяется | Плюсы | Минусы |
|---|---|---|---|
woocommerce_before_calculate_totals | Корзина | Динамическое изменение, пересчет итогов | Не влияет на цены в базе, не применяется к заказам |
woocommerce_get_price | Вывод цены на сайте | Изменяет цену везде на фронте | Не меняет цену в корзине и заказе |
woocommerce_order_item_get_total | Заказы | Изменяет цену в оформленных заказах | Не влияет на корзину и фронт |
Дополнительный пример: изменение цены товара по ID
add_action('woocommerce_before_calculate_totals', 'set_custom_price_by_product_id', 20, 1);function set_custom_price_by_product_id( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { return; } foreach ( $cart->get_cart() as $cart_item ) { if ( $cart_item['product_id'] === 1234 ) { // ID товара $cart_item['data']->set_price( 1999 ); // новая цена в рублях или валюте магазина } }}Такой код позволяет фиксировано задать цену конкретному товару при добавлении в корзину.