Диагностика задачи: зачем и когда менять цену автоматически
В WooCommerce часто возникает необходимость изменять цену товара динамически — например, для специальных акций, оптовых скидок или по условиям пользователя (роль, геолокация и т.п.). В стандартном функционале WooCommerce это реализуется вручную через купоны или изменения цены в карточке товара, что неудобно и не масштабируется.
Основные признаки задачи:
- Нужно менять цену без вмешательства администратора после обновления данных.
- Условие может быть сложным: количество в корзине, роль пользователя, дата/время, категория товара.
- Желание избежать установки громоздких плагинов, которые усложняют сайт.
Как проверить, что цена не меняется автоматически и почему
Если вы пытаетесь менять цену товара, но в корзине или на странице товара стоимость не меняется, вероятные причины:
- Фильтры WooCommerce для изменения цены не используются или применяются некорректно.
- Кэш страницы мешает обновлению цены.
- Код меняет цену после того, как WooCommerce уже рассчитала итог.
Для диагностики используйте error_log или var_dump внутри фильтров woocommerce_get_price и woocommerce_before_calculate_totals, чтобы проверить, вызываются ли они и изменяется ли цена.
Пошаговое решение: автоматическое изменение цены товара по условию
1. Использование фильтра woocommerce_before_calculate_totals
Этот фильтр позволяет изменять цену товаров в корзине перед подсчётом итогов.
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_change', 20, 1); function custom_dynamic_price_change($cart) { if (is_admin() && !defined('DOING_AJAX')) return; foreach ($cart->get_cart() as $cart_item_key => $cart_item) { $product = $cart_item['data']; // Условие: скидка 10% для пользователей с ролью 'wholesale_customer' if (current_user_can('wholesale_customer')) { $original_price = $product->get_regular_price(); $new_price = $original_price * 0.9; $product->set_price($new_price); } } }2. Изменение цен на странице товара с помощью фильтра woocommerce_product_get_price
Чтобы цена менялась и на странице товара, добавьте:
add_filter('woocommerce_product_get_price', 'custom_dynamic_product_price', 10, 2); add_filter('woocommerce_product_get_regular_price', 'custom_dynamic_product_price', 10, 2); function custom_dynamic_product_price($price, $product) { if (current_user_can('wholesale_customer')) { $price = $price * 0.9; } return $price; }3. Дополнительные условия: скидка по количеству товаров
Можно менять цену в зависимости от количества товаров в корзине:
add_action('woocommerce_before_calculate_totals', 'bulk_discount_price_change', 20, 1); function bulk_discount_price_change($cart) { if (is_admin() && !defined('DOING_AJAX')) return; $total_quantity = 0; foreach ($cart->get_cart() as $cart_item) { $total_quantity += $cart_item['quantity']; } if ($total_quantity >= 10) { foreach ($cart->get_cart() as $cart_item) { $product = $cart_item['data']; $price = $product->get_regular_price(); $product->set_price($price * 0.85); } } }Проверка результата после внедрения
- Очистите кэш сайта и браузера.
- Залогиньтесь под пользователем с ролью, указанной в условии.
- Добавьте товар в корзину и проверьте цену на странице товара и в корзине.
- Измените количество товаров (если есть условие по количеству) и убедитесь, что цена меняется.
- Проверьте, что для других пользователей цена остаётся стандартной.
Частые ошибки и как их исправить
- Цена не меняется в корзине: забыли менять цену через
set_price()в объекте товара в корзине. - Цена меняется, но итог в заказе неверный: не использован фильтр
woocommerce_before_calculate_totalsили он добавлен с низким приоритетом. - Цена меняется, но на странице товара — нет: не подключен фильтр к
woocommerce_product_get_price. - Изменения не видны из-за кэша: отключите кэширование страниц, либо настройте исключения для страниц WooCommerce.
Практические советы по безопасности и производительности
- Всегда проверяйте, что ваш код не выполняется в админке (кроме AJAX), чтобы избежать лишних нагрузок.
- Используйте как можно более узкие условия, чтобы не менять цену для всех подряд товаров без необходимости.
- Для сложных сценариев динамического ценообразования рассмотрите возможность кешировать вычисленные цены в метаданных товара.
- Если много условий, структурируйте код в отдельные функции для удобства поддержки.
Таблица сравнения вариантов изменения цены в WooCommerce
| Метод | Преимущества | Недостатки |
|---|---|---|
Фильтр woocommerce_before_calculate_totals | Меняет цену в корзине, гибкий, не требует плагинов | Цена не меняется на странице товара без дополнительного кода |
Фильтр woocommerce_product_get_price | Меняет цену на странице товара, подходит для динамического отображения | Не влияет на итоговую цену в корзине без woocommerce_before_calculate_totals |
| Плагины динамического ценообразования | Простота настройки, множество готовых опций | Дополнительная нагрузка, стоимость, возможные конфликты |