Диагностика задачи: зачем менять цену в зависимости от роли
В WooCommerce стандартно нет возможности назначать разные цены для одного и того же товара для различных групп пользователей. Однако в реальных проектах часто требуется: оптовые покупатели видят скидки, партнеры получают особые цены, а простые посетители — обычные. Без такого функционала сложно гибко управлять ценообразованием и маркетингом.
Если вы столкнулись с этим, проверьте, что у вас есть несколько ролей пользователей с четко настроенными правами и что цены надо менять именно на уровне вывода и добавления в корзину, а не просто для отображения.
Пошаговое решение: как реализовать изменение цены товара по роли
1. Добавляем фильтр для изменения цены перед выводом
Используем хук woocommerce_product_get_price и woocommerce_product_get_regular_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);
function change_price_by_user_role($price, $product) {
if (!is_user_logged_in()) {
return $price; // гость видит стандартную цену
}
$user = wp_get_current_user();
$roles = $user->roles;
// Пример: для роли wholesale - скидка 20%
if (in_array('wholesale', $roles)) {
$price = $price * 0.8;
} elseif (in_array('vip_customer', $roles)) {
$price = $price * 0.9; // скидка 10%
}
return $price;
}
2. Изменяем цену при добавлении товара в корзину
Важно также менять цену при добавлении товара в корзину, иначе в корзине и на странице товара цены будут отличаться.
add_action('woocommerce_before_calculate_totals', 'change_cart_item_price_by_role', 10, 1);
function change_cart_item_price_by_role($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
if (!is_user_logged_in()) {
return;
}
$user = wp_get_current_user();
$roles = $user->roles;
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$price = $product->get_price();
if (in_array('wholesale', $roles)) {
$new_price = $price * 0.8;
} elseif (in_array('vip_customer', $roles)) {
$new_price = $price * 0.9;
} else {
$new_price = $price;
}
if ($new_price != $price) {
$cart_item['data']->set_price($new_price);
}
}
}
Проверка результата
- Залогиньтесь под пользователем с ролью
wholesaleи проверьте, что цена на странице товара и в корзине на 20% ниже базовой. - Залогиньтесь под пользователем с ролью
vip_customer— цена должна быть ниже на 10%. - Выйдите из системы или используйте аккаунт без специальных ролей — цены должны оставаться базовыми.
- Добавьте товар в корзину, проверьте итоговую сумму и цены в заказе.
- Для более точной проверки можно использовать плагин Query Monitor, чтобы отследить, что фильтры срабатывают.
Частые ошибки и их исправление
- Цена меняется на странице товара, но не в корзине: забыли добавить логику в
woocommerce_before_calculate_totals. - Цена меняется только для некоторых товаров: проверьте, что ваша функция получает правильный объект товара и что нет конфликтов с другими плагинами, которые кешируют цены.
- Изменения не видны для гостей: в коде есть проверка
is_user_logged_in(), гостям возвращается стандартная цена. - Скидка применяется некорректно: проверьте тип данных цены, используйте
floatval()для арифметики, чтобы избежать ошибок с типами. - Конфликты с плагинами ценообразования: попробуйте временно отключить сторонние плагины, чтобы изолировать проблему.
Практические советы по безопасности и производительности
- Не храните изменённые цены в базе — меняйте их динамически через фильтры, чтобы избежать рассинхронизации и сложностей с отчетами.
- Минимизируйте количество запросов в функцию изменения цены — кэшируйте роль пользователя в сессии или глобальной переменной.
- Если требуется сложная логика ценообразования, рассмотрите кастомные метаданные товара для разных групп, но тогда потребуется расширять админку.
- Обязательно тестируйте код на тестовом сайте, чтобы избежать ошибок ценообразования в продакшене.
- Для более удобного управления ролями и скидками можно использовать плагин Clearfy Pro с функциями оптимизации WooCommerce — https://wpshop.ru/plugins/clearfy?utm_source=wpqa.ru&utm_medium=article&utm_campaign=izmenit-stoimost-tovara-woocommerce-v-zavisimosti-ot-rolli-polzovatelya
Сравнение вариантов реализации
| Метод | Плюсы | Минусы | Пример использования |
|---|---|---|---|
| Фильтры WooCommerce (код) | Гибкость, не требует сторонних плагинов, легко кастомизируется | Требует навыков программирования, возможны конфликты с другими плагинами | Пример кода выше |
| Плагины для ценообразования (например, WooCommerce Role Based Pricing) | Простота настройки через UI, поддержка сложных правил | Платные, могут создавать нагрузку, меньше гибкости в кастомизации | Использование готового решения |
| Кастомные метаполя с отдельным ценовым уровнем | Высокая точность настройки, можно иметь несколько уровней цен | Сложно реализовать без сторонних плагинов, требует доработки админки | Комбинирование кода и ACF (Advanced Custom Fields) |