Диагностика задачи: почему нужна разная цена для разных ролей
В стандартном WooCommerce цена товара фиксирована для всех пользователей. Однако в магазинах с разными категориями клиентов (например, оптовики, розничные покупатели, партнеры) требуется показывать и использовать разные цены в зависимости от роли пользователя. Это позволяет гибко управлять ценовой политикой и стимулировать определенные группы покупателей.
Как реализовать изменение цены по ролям пользователей в WooCommerce
Подход без плагинов: настраиваем через фильтры WooCommerce
Для изменения цены динамически используем фильтр woocommerce_get_price. Ниже пример кода, который изменяет цену, если пользователь имеет роль wholesale_customer — цена уменьшается на 20%:
add_filter('woocommerce_get_price', 'custom_price_by_user_role', 10, 2);
function custom_price_by_user_role($price, $product) {
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;
}Этот код нужно добавить в файл functions.php вашей дочерней темы или в плагин для пользовательских функций.
Поддержка роли гостя и других ролей
Если нужно задать цену для гостевых пользователей или других ролей, расширьте условие:
add_filter('woocommerce_get_price', 'custom_price_by_user_role_extended', 10, 2);
function custom_price_by_user_role_extended($price, $product) {
if (!is_user_logged_in()) {
// цена для гостей
$price = $price * 1.1; // например, наценка 10%
} else {
$user = wp_get_current_user();
if (in_array('wholesale_customer', (array) $user->roles)) {
$price = $price * 0.8;
} elseif (in_array('vip_customer', (array) $user->roles)) {
$price = $price * 0.9;
}
}
return $price;
}Проверка результата после внедрения
Чтобы убедиться, что цены меняются корректно:
- Зайдите под аккаунтом с ролью
wholesale_customer. На страницах товаров цена должна быть на 20% ниже базовой. - Зайдите под другим пользователем (например,
vip_customer) — проверьте, что цена соответствует установленному коэффициенту. - Откройте страницу товара без авторизации — должна отображаться цена с наценкой, если вы это настроили.
- Добавьте товар в корзину и проверьте итоговую стоимость в корзине и на странице оформления заказа.
Для проверки используйте режим инкогнито для гостевого пользователя и разные аккаунты с нужными ролями.
Частые ошибки и как их исправить
- Цена не меняется: проверьте, что роль пользователя указана правильно и пользователь действительно авторизован.
- Изменение цены не отображается в корзине или на странице оформления заказа: фильтр
woocommerce_get_priceприменяется только для отображения. Для корректного изменения цены в заказах нужно дополнительно использовать фильтрwoocommerce_before_calculate_totals(см. ниже). - Ошибка в расчетах из-за округления: используйте функции
wc_format_decimal()иwc_get_price_to_display()для правильного форматирования. - Конфликты с плагинами кеширования: при включенном кешировании цены могут кэшироваться для всех пользователей одинаково. Настройте исключения кеша для страниц с ценами или используйте AJAX для динамического обновления.
Расширенное решение: изменение цены в корзине и заказах
Чтобы цена учитывалась при добавлении товара в корзину и правильном расчете итогов, добавьте следующий код:
add_action('woocommerce_before_calculate_totals', 'custom_price_cart_by_user_role', 10);
function custom_price_cart_by_user_role($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (!is_user_logged_in()) {
$role = 'guest';
} else {
$user = wp_get_current_user();
$roles = $user->roles;
$role = reset($roles); // берем первую роль
}
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$price = $product->get_regular_price();
switch ($role) {
case 'wholesale_customer':
$new_price = $price * 0.8;
break;
case 'vip_customer':
$new_price = $price * 0.9;
break;
case 'guest':
$new_price = $price * 1.1;
break;
default:
$new_price = $price;
}
$product->set_price($new_price);
}
}Этот код гарантирует, что цена товара в корзине и в заказе будет соответствовать установленным правилам для ролей.
Чек-лист для реализации изменения цен по ролям в WooCommerce
- Определить роли пользователей, для которых нужна разная цена.
- Добавить фильтр
woocommerce_get_priceдля изменения отображаемой цены. - Добавить обработчик
woocommerce_before_calculate_totalsдля изменения цены в корзине. - Проверить отображение цены на страницах товаров для разных пользователей.
- Проверить итоговую стоимость в корзине и на оформлении заказа.
- Проверить совместимость с кеширующими плагинами и настроить исключения.
- Тестировать на разных ролях и гостях.
Сравнение вариантов реализации
| Метод | Преимущества | Недостатки |
|---|---|---|
Только фильтр woocommerce_get_price | Простая реализация, быстрое изменение цены на фронтенде | Не меняет цену в корзине и заказах, возможны рассогласования |
Фильтр + woocommerce_before_calculate_totals | Полное изменение цены на сайте, в корзине и заказах | Сложнее в реализации, требует тщательного тестирования |
| Плагины для цен по ролям | Готовые решения с интерфейсом, поддержкой и настройками | Дополнительные расходы, возможные конфликты, нагрузка |
Практические советы по безопасности и производительности
- Не храните несколько цен в метаполях вручную, если не используете плагины — это усложнит поддержку.
- Избегайте тяжелых вычислений в фильтрах, особенно
woocommerce_before_calculate_totals, чтобы не замедлять процесс оформления заказа. - Кэшируйте результаты функций, если цена вычисляется по сложным правилам.
- Тестируйте код на разных версиях PHP и WooCommerce, чтобы избежать конфликтов.
- Используйте дочернюю тему или плагин для внесения изменений, чтобы не потерять их при обновлениях.
- Обязательно делайте бэкап перед внесением изменений.