Диагностика задачи: зачем менять цену товара программно
В WooCommerce иногда возникает необходимость динамически менять цену товара в зависимости от конкретных условий — например, при заказе определённого количества, для конкретной роли пользователя или при наличии скидочного купона. Обычные скидки и акции не всегда покрывают такие сценарии, поэтому приходится внедрять изменения на уровне кода.
Основная сложность — корректно изменить цену до момента расчёта корзины и оформления заказа, чтобы WooCommerce правильно отобразил стоимость, а покупатель видел актуальные данные.
Как работает изменение цены товара в WooCommerce: ключевые хуки
Для изменения цены используются фильтры, которые WooCommerce вызывает при вычислении стоимости товара в корзине и на странице товара. Основные из них:
woocommerce_get_price— изменяет цену товара при выводе на сайте;woocommerce_product_get_priceиwoocommerce_product_get_regular_price— фильтры для получения цены продукта;woocommerce_before_calculate_totals— хук, где можно изменить цену непосредственно в объекте товара в корзине.
Для практического изменения цены в корзине рекомендуют использовать woocommerce_before_calculate_totals, так как он позволяет динамически менять цену именно для корзинных объектов.
Пошаговое решение: изменение цены товара в корзине при заказе более 5 штук
Шаг 1. Добавляем код в functions.php или отдельный плагин
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_by_quantity', 10, 1);
function custom_dynamic_price_by_quantity($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item) {
$quantity = $cart_item['quantity'];
$product = $cart_item['data'];
$original_price = floatval($product->get_regular_price());
// Условие: если куплено больше 5 штук, скидка 10%
if ($quantity > 5) {
$new_price = $original_price * 0.9;
$product->set_price($new_price);
} else {
$product->set_price($original_price);
}
}
}Шаг 2. Проверяем результат на сайте
Перейдите в корзину и добавьте товар в количестве более 5 штук. В поле цены должна автоматически отразиться скидка 10%. При уменьшении количества до 5 и ниже цена возвращается к исходной.
Проверка результата после внедрения
- Добавьте товар в корзину с количеством 4 — цена должна оставаться без изменений.
- Измените количество на 6 и обновите корзину — цена должна снизиться на 10%.
- Проверьте оформление заказа — итоговая сумма должна учитывать новую цену.
- Проверьте, что в админке и на странице товара цена не изменилась, только в корзине.
Частые ошибки и как их исправить
- Цена не меняется в корзине: возможно, забыли проверить
is_admin()или хук подключён с неправильным приоритетом. Используйте приоритет 10 и проверяйте условиеif (is_admin() && !defined('DOING_AJAX')) return;. - Цена меняется и на странице товара: изменение цены происходит напрямую в объекте товара без проверки контекста. Используйте хук
woocommerce_before_calculate_totals, он срабатывает только для корзины. - Скидка применяется некорректно: убедитесь, что используете правильное значение цены —
get_regular_price(), а неget_price(), если хотите базовую цену без скидок. - Кэш мешает обновлению цены: очистите кэш сайта и браузера, если используете кэширующие плагины.
Практические советы по безопасности и производительности
- Не меняйте цену в глобальном объекте товара вне корзины, чтобы избежать конфликтов с другими плагинами.
- Проверяйте, что код не выполняется в админке и во время AJAX-запросов, чтобы не нарушить работу административной панели.
- Используйте минимально необходимые вычисления — например, кешируйте результаты для большого количества товаров в корзине.
- Тестируйте изменения с разными ролями пользователей и вариантами оформления заказа, чтобы избежать неожиданных проблем.
Сравнение методов изменения цены в WooCommerce
| Метод | Где применяется | Плюсы | Минусы |
|---|---|---|---|
| woocommerce_before_calculate_totals | Корзина | Динамическое изменение цены, работает в корзине и на оформлении | Не влияет на цену на странице товара |
| woocommerce_get_price | Вывод цены на страницах | Меняет цену на страницах товара | Не меняет цену в корзине, может вызвать конфликты |
| woocommerce_product_get_price | Объект продукта | Универсальный фильтр цены | Сложно контролировать контекст, могут быть ошибки |