Диагностика задачи: зачем менять цены по ролям в WooCommerce
В интернет-магазинах на WooCommerce часто возникает необходимость показывать разные цены для разных групп покупателей — например, оптовым клиентам или зарегистрированным дилерам. Встроенных средств для этого нет, стандартный функционал WooCommerce не поддерживает разные цены для ролей. Без кастомизации или плагинов изменить цену товара динамически сложно.
Типичная проблема — попытка изменить цену через стандартные фильтры, но при этом цены не обновляются в корзине или на странице товара, либо цена меняется только для гостя. Для решения нужно учитывать все места, где цена выводится и рассчитывается.
Пошаговое решение: автоматическое изменение цены по ролям
1. Определяем роли пользователей
Для начала убедитесь, что нужные роли существуют. Например, добавим роль «оптовик» если её нет:
function add_wholesale_role() {
add_role('wholesaler', 'Оптовик', array(
'read' => true,
'level_0' => true
));
}
add_action('init', 'add_wholesale_role');
2. Создаем функцию фильтра для изменения цены
Используем хук woocommerce_product_get_price и аналогичные для разных типов цен:
function change_price_for_wholesaler($price, $product) {
if (is_admin()) return $price; // не меняем в админке
if (is_user_logged_in()) {
$user = wp_get_current_user();
if (in_array('wholesaler', (array) $user->roles)) {
// Например, скидка 20%
$price = $price * 0.8;
}
}
return $price;
}
add_filter('woocommerce_product_get_price', 'change_price_for_wholesaler', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'change_price_for_wholesaler', 10, 2);
add_filter('woocommerce_product_get_sale_price', 'change_price_for_wholesaler', 10, 2);
3. Обновляем цены в корзине и заказе
Для корректного расчёта применим хук woocommerce_before_calculate_totals:
function apply_wholesale_price_in_cart($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (!is_user_logged_in()) return;
$user = wp_get_current_user();
if (!in_array('wholesaler', (array) $user->roles)) return;
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$price = $product->get_price();
$wholesale_price = $price * 0.8; // скидка 20%
$cart_item['data']->set_price($wholesale_price);
}
}
add_action('woocommerce_before_calculate_totals', 'apply_wholesale_price_in_cart', 10, 1);
4. Кэширование и производительность
Избегайте излишних вычислений — кэшируйте результат, если цена не меняется часто. Можно сохранять цену в метаполе пользователя или товара, если логика сложнее.
Проверка результата после внедрения
- Залогиньтесь под пользователем с ролью
wholesalerи откройте страницу товара — цена должна быть на 20% ниже обычной. - Добавьте товар в корзину — проверьте, что в корзине и при оформлении заказа цена соответствует изменённой.
- Залогиньтесь под обычным пользователем или гостем — цена должна быть стандартной.
Частые ошибки и как исправить
- Цена не меняется на странице товара — проверьте, что фильтры
woocommerce_product_get_priceподключены и не конфликтуют с плагинами кэширования. - Цена меняется, но не в корзине — не забывайте про
woocommerce_before_calculate_totals, без него цена в корзине останется базовой. - Изменения видны в админке — добавьте проверку
is_admin()чтобы не менять цены в административной панели. - Конфликты с плагинами скидок — убедитесь, что ваша логика не дублирует скидки и корректно взаимодействует с другими плагинами.
Практические советы по безопасности и производительности
- Не сохраняйте цены для ролей напрямую в базу без необходимости, используйте динамические фильтры — так проще обновлять логику.
- Минимизируйте количество дополнительных запросов к базе, кешируя результаты.
- Если используете сложные правила ценообразования, рассматривайте плагины, например, WPShop Clearfy Pro для оптимизации SEO и удаления дублей, которые могут повлиять на индексацию цен.
Сравнение вариантов реализации изменения цен по ролям
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
| Код через фильтры WooCommerce | Гибко, бесплатно, прямой контроль | Нужно писать и тестировать, возможны конфликты | Описание в статье |
| Плагины (например, WooCommerce Role Based Pricing) | Удобно, готовые функции, поддержка | Платно, нагрузка на сайт | Плагин из репозитория |
| Пользовательские поля и метаполя | Хранение разных цен в базе | Сложнее реализовать динамическое применение | Нужно дописывать код |