Диагностика задачи: почему нужно менять цены автоматически
В интернет-магазинах на WooCommerce часто возникает необходимость менять стоимость товаров динамически в зависимости от различных условий: например, даты акции, роли пользователя, объема заказа или регионов доставки. Ручное изменение цен неудобно и чревато ошибками, особенно при большом ассортименте или частых акциях.
Задача: настроить автоматическое изменение цены товара без установки громоздких плагинов, используя возможности WooCommerce и WordPress.
Как реализовать автоматическое изменение цены в WooCommerce
Какие хуки использовать для изменения цены
WooCommerce предоставляет фильтры, которые позволяют менять цену товара «на лету» при выводе и при добавлении в корзину. Основные хуки для этого:
woocommerce_product_get_price— для получения основной цены товара;woocommerce_product_get_regular_price— для обычной цены (без скидок);woocommerce_product_get_sale_price— для цены со скидкой;woocommerce_before_calculate_totals— для изменения цены в корзине;woocommerce_cart_item_priceиwoocommerce_cart_item_subtotal— для отображения цены в корзине.
Пошаговое решение: пример изменения цены по роли пользователя
Допустим, нужно сделать специальную цену для пользователей с ролью wholesale_customer. Для них цена товара будет снижена на 20%.
add_filter('woocommerce_product_get_price', 'custom_price_by_user_role', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'custom_price_by_user_role', 10, 2);
add_filter('woocommerce_product_get_sale_price', 'custom_price_by_user_role', 10, 2);
function custom_price_by_user_role($price, $product) {
if (is_admin()) return $price; // не менять в админке
if (is_user_logged_in()) {
$user = wp_get_current_user();
if (in_array('wholesale_customer', (array) $user->roles)) {
$price = $price * 0.8; // скидка 20%
}
}
return $price;
}
// Обновляем цену в корзине
add_action('woocommerce_before_calculate_totals', 'custom_cart_price_by_user_role', 10, 1);
function custom_cart_price_by_user_role($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (is_user_logged_in()) {
$user = wp_get_current_user();
if (in_array('wholesale_customer', (array) $user->roles)) {
foreach ($cart->get_cart() as $cart_item) {
$original_price = $cart_item['data']->get_price();
$new_price = $original_price * 0.8;
$cart_item['data']->set_price($new_price);
}
}
}
}Этот код изменяет цену товара и в каталоге, и в корзине, если пользователь с нужной ролью.
Проверка результата после внедрения
- Залогиньтесь под пользователем с ролью
wholesale_customerи под обычным пользователем; - Проверьте отображение цены товара в каталоге и на странице товара — должна применяться скидка 20% только для wholesale_customer;
- Добавьте товар в корзину и убедитесь, что цена там тоже пересчитана;
- Для полного теста проверьте оформление заказа, чтобы скидка корректно сохранилась.
Частые ошибки и как их исправить
- Изменение цены в админке. Если не проверять
is_admin(), цена может стать некорректной при редактировании товара. Всегда добавляйте условиеif (is_admin()) return $price;. - Цена не меняется в корзине. Не забывайте использовать хук
woocommerce_before_calculate_totalsи устанавливать цену через$cart_item['data']->set_price(). Если этого не сделать, измененная цена не отобразится при оформлении заказа. - Кэширование мешает обновлению цены. Если на сайте включено кэширование (например, через плагин или серверный кэш), цены могут не обновляться для разных пользователей. В этом случае настройте исключения по кукам или URL.
Практические советы по безопасности и производительности
- Не используйте тяжелые запросы в фильтрах цены. Они вызываются при каждом отображении товаров, поэтому сложные запросы в базу данных или API лучше выносить в кеш или предварительно рассчитывать.
- Кэшируйте результат вычисления скидки. Например, сохраните значение скидки для пользователя в сессии или transient, чтобы не вычислять при каждом вызове.
- Ограничьте изменение цены только необходимыми страницами. Например, используйте
is_product() || is_shop() || is_cart() || is_checkout()для уменьшения нагрузки.
Сравнение способов изменения цены в WooCommerce
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
Фильтры woocommerce_product_get_price | Простая реализация, работает на фронтенде | Не меняет цену в корзине автоматически | Для изменения цены при отображении товара |
Хук woocommerce_before_calculate_totals | Меняет цену в корзине и при оформлении заказа | Нужно писать дополнительный код, сложнее | Для динамического изменения цены в корзине |
| Плагины для скидок | Удобный интерфейс, много функций | Большой вес, может конфликтовать с кастомным кодом | Для сложных акций и маркетинговых кампаний |