Диагностика задачи: зачем менять стоимость товара программно
В WooCommerce часто возникает необходимость динамически изменять цену товара на основе различных условий — скидок, акций, количества в корзине, геолокации пользователя и т.п. Без грамотного использования хуков можно столкнуться с проблемами некорректного отображения цены или конфликтах с другими плагинами.
Основные хуки для изменения цены товара
Для изменения стоимости товара в WooCommerce наиболее полезны следующие хуки и фильтры:
woocommerce_product_get_price— изменяет цену товара для отображения на сайтеwoocommerce_product_get_regular_price— изменяет базовую цену товараwoocommerce_before_calculate_totals— позволяет изменить цену товара в корзине перед подсчетом итогов
Пример: изменение цены товара в корзине
Чтобы изменить цену товара в корзине, нужно добавить фильтр на хук woocommerce_before_calculate_totals. Это гарантирует, что цена изменится только в корзине, а не на странице товара.
add_action('woocommerce_before_calculate_totals', 'custom_change_cart_item_price', 20, 1);function custom_change_cart_item_price( $cart_object ) { if ( is_admin() && ! defined('DOING_AJAX') ) return; foreach ( $cart_object->get_cart() as $cart_item ) { // Пример: увеличить цену на 10% $original_price = $cart_item['data']->get_price(); $new_price = $original_price * 1.1; $cart_item['data']->set_price( $new_price ); }}Пример: изменение цены на странице товара
Если нужно динамически изменить цену на странице товара (например, показывать цену со скидкой для определенной категории пользователей), используют фильтр woocommerce_product_get_price:
add_filter( 'woocommerce_product_get_price', 'custom_dynamic_price_display', 10, 2 );function custom_dynamic_price_display( $price, $product ) { if ( current_user_can('customer') && $product->is_on_sale() ) { // Показываем скидку 20% для клиентов return $price * 0.8; } return $price;}Пошаговое решение: меняем цену товара на 15% для пользователей из определенной страны
Задача: покупатели из России получают скидку 15% на все товары.
- Определить страну пользователя. Можно использовать IP-геолокацию или данные из адреса доставки. Для простоты — через сессию или куки (в примере используем шорткод для установки).
- Добавить фильтр к
woocommerce_before_calculate_totalsдля изменения цены в корзине. - Добавить фильтр к
woocommerce_product_get_price, чтобы изменить цену на странице товара.
// Пример определения страны (для теста ставим вручную)function set_user_country() { if ( ! isset( $_COOKIE['user_country'] ) ) { setcookie('user_country', 'RU', time()+3600*24, COOKIEPATH, COOKIE_DOMAIN); }}add_action('init', 'set_user_country');function is_user_from_ru() { return ( isset($_COOKIE['user_country']) && $_COOKIE['user_country'] === 'RU' );}// Изменяем цену на странице товараadd_filter( 'woocommerce_product_get_price', 'discount_for_ru_customers', 10, 2 );function discount_for_ru_customers( $price, $product ) { if ( is_user_from_ru() ) { return $price * 0.85; } return $price;}// Изменяем цену в корзинеadd_action('woocommerce_before_calculate_totals', 'discount_for_ru_cart_items', 20, 1);function discount_for_ru_cart_items( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( ! is_user_from_ru() ) return; foreach ( $cart->get_cart() as $cart_item ) { $price = $cart_item['data']->get_price(); $cart_item['data']->set_price( $price * 0.85 ); }}Проверка результата после внедрения кода
- На странице товара для пользователя из России должна отображаться цена со скидкой 15%.
- В корзине и на странице оформления заказа цены товаров должны быть снижены на 15%.
- Для пользователей из других стран цена не меняется.
- Чтобы проверить, можно вручную удалить куки или изменить значение
user_country.
Частые ошибки и как их исправить
- Цена не меняется в корзине. Проверьте, что функция-хук подключена именно на
woocommerce_before_calculate_totalsи что цена меняется через методset_price()у объекта товара в корзине. - Изменяется цена на странице товара, но не в корзине. Размер скидки должен применяться и там, и там через соответствующие хуки. Не используйте только фильтры для отображения, если нужно изменить итоговую стоимость.
- Проблемы с кешированием. Если сайт использует агрессивный кеш, цены могут не обновляться. Нужно исключить страницы корзины и товара из кеша или использовать AJAX для динамического обновления.
- Использование IP-геолокации без кэширования. Частые запросы к внешним сервисам замедляют сайт. Лучше сохранять результат в сессии или куках.
Практические советы по безопасности и производительности
- Не изменяйте цены напрямую в базе без использования хуков — это приведет к рассинхронизации и возможным багам.
- Для больших магазинов с кешем используйте AJAX-подгрузку цены, если скидка зависит от сессии или геолокации.
- Всегда проверяйте, что код не запускается в админке, чтобы избежать влияния на панель управления.
- Используйте проверенные методы определения страны пользователя, например, плагины GeoIP или WooCommerce Geolocation.
Сравнение способов изменения цены: хуки vs плагины
| Метод | Преимущества | Недостатки | Компромисс |
|---|---|---|---|
| Использование хуков (код в functions.php или плагине) | Гибкость, полный контроль, минимально зависит от сторонних решений | Требует знаний PHP, возможны ошибки при неправильной реализации | Использовать для уникальных бизнес-логик |
| Готовые плагины для скидок и динамического ценообразования | Быстрая настройка, поддержка, интеграция с WooCommerce | Могут быть тяжелыми, не всегда подходят под кастомные задачи | Использовать для стандартных сценариев, если нет сложной логики |