Диагностика задачи: зачем менять цены динамически в WooCommerce
В стандартном WooCommerce цены на товары статичны и берутся из настроек продукта. Однако бывают задачи, когда цену нужно менять в зависимости от условий: пользовательских ролей, времени суток, количества в корзине, параметров заказа или других факторов. Например, показывать скидку только определённым пользователям или менять цену в зависимости от даты.
Без правильного подхода можно столкнуться с проблемами: неправильным отображением цен, конфликтами с кешированием и некорректными итогами заказа.
Основные хуки WooCommerce для изменения цены
WooCommerce предоставляет несколько фильтров для изменения цены товара в процессе отображения и расчёта:
woocommerce_get_price— изменяет базовую цену товара;woocommerce_get_sale_price— меняет цену распродажи;woocommerce_product_get_priceиwoocommerce_product_get_regular_price— объектно-ориентированные фильтры для получения цен;woocommerce_before_calculate_totals— позволяет менять цену товаров в корзине перед подсчётом итогов.
Пошаговое решение: динамическая смена цены по роли пользователя
Рассмотрим конкретный пример: для пользователей с ролью wholesale_customer дать скидку 20% на все товары.
1. Изменение цены в каталоге и на страницах товаров
add_filter('woocommerce_product_get_price', 'change_price_for_wholesale', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'change_price_for_wholesale', 10, 2);
function change_price_for_wholesale($price, $product) {
if (is_admin()) return $price; // не менять в админке
if (current_user_can('wholesale_customer')) {
$price = $price * 0.8; // скидка 20%
}
return $price;
}2. Обновление цены в корзине и при оформлении заказа
add_action('woocommerce_before_calculate_totals', 'apply_wholesale_price_in_cart');
function apply_wholesale_price_in_cart($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (current_user_can('wholesale_customer')) {
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$price = $product->get_regular_price() * 0.8;
$cart_item['data']->set_price($price);
}
}
}Проверка результата после внедрения
- Очистите кеш сайта и браузера.
- Войдите под пользователем с ролью
wholesale_customerи убедитесь, что цена на странице товара и в корзине уменьшена на 20%. - Залогиньтесь под другим пользователем — цена должна отображаться без скидки.
- Проверьте итоговую сумму заказа — скидка должна применяться корректно.
Частые ошибки и как их исправить
- Цена не меняется на странице товара
— проверьте, что фильтры применяются правильно и не конфликтуют с кешем. Отключите кеширование или добавьте исключения. - Цены меняются в админке
— не забудьте условиеis_admin(), чтобы не ломать интерфейс управления товарами. - Скидка не учитывается в корзине
— важно использоватьwoocommerce_before_calculate_totalsи менять цену через методset_price()объекта товара в корзине. - Конфликты с другими плагинами скидок
— внимательно протестируйте вместе с другими плагинами, иногда они перезаписывают цену позже.
Практические советы по безопасности и производительности
- Всегда проверяйте права пользователя через
current_user_can(), чтобы избежать неправильного отображения цен. - Избегайте тяжелых запросов или сложной логики в фильтрах цен — используйте кеширование, если требуется вычислять цену динамически.
- Тестируйте после обновления WooCommerce — API и хуки могут меняться.
Сравнение способов изменения цены в WooCommerce
| Метод | Где применяется | Плюсы | Минусы |
|---|---|---|---|
Фильтры woocommerce_product_get_price | Отображение цены на сайте | Простой способ менять цену без изменения данных в базе | Не влияет на цену в корзине и заказе без дополнительного кода |
Хук woocommerce_before_calculate_totals | Корзина и оформление заказа | Позволяет менять цену для расчёта итогов | Нужно синхронизировать с изменением цены на сайте |
| Плагины скидок | Готовые решения | Удобны и часто имеют UI | Могут быть тяжёлыми и конфликтовать |