WooCommerce: как использовать хуки для автоматического изменения стоимости товаров

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

В 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% на все товары.

  1. Определить страну пользователя. Можно использовать IP-геолокацию или данные из адреса доставки. Для простоты — через сессию или куки (в примере используем шорткод для установки).
  2. Добавить фильтр к woocommerce_before_calculate_totals для изменения цены в корзине.
  3. Добавить фильтр к 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Могут быть тяжелыми, не всегда подходят под кастомные задачиИспользовать для стандартных сценариев, если нет сложной логики
WooCommerce: как избежать проблем с отображением атрибутов вариаций в корзине
03.06.2026
Как удалить мета-данные при удалении записи в WordPress
25.03.2026
WooCommerce: решение проблемы отображения товаров с разными вариациями в корзине
07.05.2026
Автоматический импорт продуктов в WordPress с помощью WP All Import
09.01.2026
Автоматическое удаление неактивных пользователей WordPress
21.03.2026