Проблема: зачем менять цену товара динамически без правки в админке?
В стандартном WooCommerce цена товара задаётся в админке и сохраняется в базе. Но иногда требуется изменить цену для пользователя или условия показа (например, в зависимости от роли, времени, акции), не меняя саму цену в карточке товара. Это полезно для динамических скидок, персонализации, тестирования цен или интеграции с внешними сервисами.
Диагностика: почему простая смена цены в админке не подходит?
- Изменение цены в админке влияет на всех покупателей и сохраняется навсегда.
- Может быть множество условий, которые невозможно учесть вручную.
- При использовании кэширования и CDN важно менять цену на этапе вывода, а не в базе.
Пошаговое решение: как программно изменить цену на лету через фильтры WooCommerce
WooCommerce предоставляет фильтры woocommerce_get_price и woocommerce_product_get_price, с помощью которых можно динамически изменить цену товара при выводе.
Пример кода, который изменит цену для гостей, уменьшая её на 10%:
add_filter('woocommerce_product_get_price', 'custom_dynamic_price', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'custom_dynamic_price', 10, 2);
add_filter('woocommerce_product_get_sale_price', 'custom_dynamic_price', 10, 2);
function custom_dynamic_price($price, $product) {
if (!is_user_logged_in()) { // для гостей
$new_price = $price * 0.9; // 10% скидка
return round($new_price, 2);
}
return $price;
}Если нужно менять цену только на витрине (каталоге), без изменения в корзине и на страницах заказа, можно добавить проверку контекста:
function custom_dynamic_price_catalog($price, $product) {
if (is_admin()) {
return $price; // не менять в админке
}
if (is_shop() || is_product_category() || is_product_tag()) {
return $price * 0.9;
}
return $price;
}
add_filter('woocommerce_product_get_price', 'custom_dynamic_price_catalog', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'custom_dynamic_price_catalog', 10, 2);
add_filter('woocommerce_product_get_sale_price', 'custom_dynamic_price_catalog', 10, 2);Проверка результата после внедрения
- Очистите кэш сайта и браузера.
- Откройте страницу товара как гость — цена должна отображаться с учётом скидки.
- Войдите под пользователем — цена должна быть стандартной.
- Добавьте товар в корзину и проверьте цену там — она будет исходной, если не добавлять фильтры для корзины.
Частые ошибки и как их исправить
- Цена меняется в админке или базе данных — фильтры работают только на вывод, не меняйте напрямую мета-данные
_price. - Цена не меняется на страницах корзины и оформления заказа — добавьте фильтры
woocommerce_cart_item_priceиwoocommerce_cart_item_subtotalили используйтеwoocommerce_before_calculate_totalsдля изменения цены в корзине. - Проблемы с кэшированием — отключите кэширование страниц или используйте AJAX для динамического обновления цены.
- Неверное округление цены — используйте
round()с двумя знаками после запятой.
Практические советы по безопасности и производительности
- Не храните динамические цены в базе данных, чтобы избежать рассинхронизации.
- Используйте кеширование с умом — если цена зависит от пользователя, кэшируйте индивидуально или отключайте кэш для таких страниц.
- Избегайте тяжелых запросов внутри фильтров цены — лучше заранее подготовить данные.
Сравнение вариантов реализации динамического изменения цены
| Метод | Плюсы | Минусы |
|---|---|---|
Фильтры WooCommerce (woocommerce_product_get_price) |
Просто, работает на выводе, не меняет базу | Не меняет цену в корзине по умолчанию, надо дописывать |
Изменение мета-данных товара (update_post_meta) |
Меняет цену для всех, можно интегрировать с внешними системами | Меняет базу, приведёт к путанице, требует отката |
| Использование плагинов (например, Dynamic Pricing) | Готовые решения с интерфейсом и поддержкой | Тяжелее, может быть избыточно, платные |