Диагностика задачи: зачем менять цены по ролям пользователей в WooCommerce
В интернет-магазинах на WooCommerce часто возникает задача предоставить разные цены для разных групп покупателей: оптовиков, постоянных клиентов, партнеров. Это позволяет гибко управлять ценовой политикой без необходимости создавать отдельные товары или использовать отдельные магазины.
Основные признаки необходимости автоматического изменения цен:
- Разные цены должны показываться уже на странице товара и в корзине;
- Необходимо сохранить простоту управления товарами без дублирования записей;
- Цена должна корректно отображаться для гостей и зарегистрированных пользователей с разными ролями;
- Изменения в цене должны учитывать скидки и акции WooCommerce.
Как реализовать изменение цены товаров по ролям пользователей в WooCommerce
Подключение пользовательских ролей
Для начала убедимся, что у вас существуют нужные роли пользователей. Если необходимо, создайте их в functions.php или через плагин. Пример добавления роли:
add_role('wholesaler', 'Оптовик', array(
'read' => true,
'level_0' => true
));Фильтрация цены товара на фронтенде
Основной метод — использовать фильтр woocommerce_product_get_price и woocommerce_product_get_regular_price для изменения цены товара в зависимости от роли пользователя.
function change_price_by_user_role($price, $product) {
if (is_admin()) return $price;
if (!is_user_logged_in()) return $price; // цена для гостей
$user = wp_get_current_user();
if (in_array('wholesaler', (array) $user->roles)) {
// уменьшаем цену на 20% для оптовиков
$price = $price * 0.8;
} elseif (in_array('vip_customer', (array) $user->roles)) {
// уменьшаем цену на 10% для VIP клиентов
$price = $price * 0.9;
}
return $price;
}
add_filter('woocommerce_product_get_price', 'change_price_by_user_role', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'change_price_by_user_role', 10, 2);Этот код применит скидку к цене товара в каталоге и на странице товара для пользователей с определёнными ролями.
Изменение цены в корзине и оформлении заказа
Чтобы скидка корректно применялась в корзине и на этапе оформления, нужно использовать фильтр woocommerce_before_calculate_totals для изменения цены в объекте товара корзины:
function apply_role_based_price_cart($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (!is_user_logged_in()) return;
$user = wp_get_current_user();
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
if (in_array('wholesaler', (array) $user->roles)) {
$new_price = $original_price * 0.8;
} elseif (in_array('vip_customer', (array) $user->roles)) {
$new_price = $original_price * 0.9;
} else {
$new_price = $original_price;
}
$product->set_price($new_price);
}
}
add_action('woocommerce_before_calculate_totals', 'apply_role_based_price_cart', 10, 1);Проверка результата после внедрения
- Залогиньтесь под пользователем с ролью
wholesalerи убедитесь, что цены на странице товара и в каталоге отображаются с 20% скидкой. - Проверьте корзину и оформление заказа — цена товара должна сохраняться со скидкой.
- Выйдите из системы или залогиньтесь как обычный пользователь, чтобы проверить, что цены отображаются без изменений.
- Проверьте работу с разными товарами (простой, вариативный), чтобы убедиться, что скидки применяются корректно.
Частые ошибки и как их исправить
- Цены не меняются на странице товара — проверьте, что фильтры применяются корректно и не переписываются другими плагинами. Используйте
var_dumpи логи для отладки. - Скидка не применяется в корзине — убедитесь, что функция hooked к
woocommerce_before_calculate_totalsи не раннее. - Конфликт с кешированием — кеш может показывать цены без скидок. Настройте исключения по ролям для кеша или используйте динамические блоки.
- Цена в заказах и отчетах не совпадает — всегда меняйте цену через объект товара корзины, а не напрямую в базе или метаданных.
Практические советы по безопасности и производительности
- Избегайте повторных расчетов: кешируйте рассчитанные цены в сессии или метаданных пользователя.
- Проверяйте права пользователя через
current_user_can()для более гибкой настройки ролей. - Помните, что изменение цены через фильтры не меняет цену в базе, поэтому отчеты WooCommerce могут показывать оригинальные цены.
- Тестируйте на staging-сайте и убедитесь, что ваши изменения не конфликтуют с активными плагинами безопасности и кеширования.
Сравнение способов реализации изменения цены по ролям
| Метод | Плюсы | Минусы | Применение |
|---|---|---|---|
| Фильтры WooCommerce (код) | Гибко, бесплатно, не требует плагинов | Требует навыков, может конфликтовать | Для кастомных решений |
| Плагины (например, "WooCommerce Role Based Pricing") | Просто установить и настроить | Платные, могут грузить сайт | Для быстрого запуска без кода |
| Создание отдельных товаров/каталогов | Простая логика | Дублирование товаров, сложность администрирования | Редкие случаи, сложные каталоги |