Проблема: необходимость динамического изменения цены товара
В WooCommerce часто встречается задача изменить цену товара в зависимости от определенных условий: например, скидка для определенных пользователей, сезонные акции или изменение цены при покупке определенного количества товара. В стандартном функционале WooCommerce такие сценарии реализуются через купоны или плагины, но для точечного и гибкого контроля лучше использовать хуки и программные методы.
Диагностика текущей ситуации
Прежде чем внедрять изменения, убедитесь, что:
- Вы используете последнюю версию WooCommerce.
- В вашем шаблоне нет конфликтующих фильтров или плагинов, которые уже модифицируют цену.
- Стоимость товара рассчитывается корректно при покупке без условий.
Для проверки текущих цен используйте консоль разработчика в браузере и отладочные функции WooCommerce.
Как автоматически изменить цену товара по условию
Используем хук woocommerce_get_price
Основной фильтр для изменения цены — woocommerce_get_price. Ниже пример кода, который снижает цену на 10% для пользователей с ролью «подписчик» и для товаров из категории «скидка».
add_filter('woocommerce_get_price', 'custom_dynamic_price', 10, 2); function custom_dynamic_price($price, $product) { if ( is_user_logged_in() ) { $user = wp_get_current_user(); if ( in_array('subscriber', (array) $user->roles) ) { if ( has_term('skidka', 'product_cat', $product->get_id()) ) { $price = $price * 0.9; // скидка 10% } } } return $price; }Изменение цены в корзине с помощью woocommerce_before_calculate_totals
Для динамического изменения цены при подсчете корзины используйте хук woocommerce_before_calculate_totals. Пример для скидки 15% на товары определенной категории:
add_action('woocommerce_before_calculate_totals', 'custom_cart_item_price_change'); function custom_cart_item_price_change($cart) { if ( is_admin() && ! defined('DOING_AJAX') ) return; if ( did_action('woocommerce_before_calculate_totals') >= 2 ) return; foreach ( $cart->get_cart() as $cart_item ) { $product = $cart_item['data']; if ( has_term('sale', 'product_cat', $product->get_id()) ) { $original_price = $product->get_regular_price(); $new_price = $original_price * 0.85; // скидка 15% $product->set_price($new_price); } } }Проверка результата после внедрения
- Зайдите на сайт под пользователем с нужной ролью (например, подписчик).
- Перейдите на страницу товара из категории с условием и проверьте отображаемую цену.
- Добавьте товар в корзину и убедитесь, что цена в корзине и на странице оформления заказа соответствует измененной цене.
- Проверьте, что для других пользователей и товаров цена осталась неизменной.
Частые ошибки и как их исправить
- Цена не меняется на странице товара, но меняется в корзине: Проверьте, что фильтр
woocommerce_get_priceприменяется корректно, возможно в теме есть кеширование или кэш плагина. - Измененная цена не сохраняется при оформлении заказа: Для этого нужно дополнительно обработать цену в момент создания заказа с помощью хука
woocommerce_checkout_create_order_line_item. - Конфликты с другими плагинами скидок: отключите все сторонние плагины скидок и проверьте, не перекрывают ли они ваш код.
- Цены неправильные при Ajax-обновлении корзины: убедитесь, что используете правильные хуки, а код не вызывает повторных расчетов.
Практические советы по безопасности и производительности
- Не храните измененные цены в базе данных, используйте динамические фильтры для вычислений.
- Кешируйте результаты сложных вычислений, чтобы снизить нагрузку на сервер.
- Проверяйте права пользователя через
current_user_can()вместо прямой проверки ролей для более гибкой логики. - Добавляйте проверки
is_admin()иDOING_AJAX, чтобы не влиять на административную часть и AJAX-запросы без необходимости.
Сравнение способов реализации динамической цены
| Метод | Преимущества | Недостатки | Когда использовать |
|---|---|---|---|
Фильтр woocommerce_get_price | Изменение цены на всех страницах, простота | Может не работать с кешированием темы или плагинов | Для простых изменений цены на фронтенде |
Хук woocommerce_before_calculate_totals | Изменение цены в корзине и при оформлении заказа | Не влияет на страницу товара без дополнительного кода | Для скидок, зависящих от корзины |
| Плагины скидок | Готовое решение, много функционала | Зависимость от стороннего кода, возможные конфликты | Для комплексных маркетинговых кампаний |