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

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

Часто требуется динамически менять цену товара в 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 ); // новая цена в рублях или валюте магазина        }    }}

Такой код позволяет фиксировано задать цену конкретному товару при добавлении в корзину.