Диагностика задачи: зачем менять цену товара по роли и атрибутам
Часто в WooCommerce требуется индивидуализировать цены: например, показывать оптовые цены для определённых ролей пользователей (оптовики, дилеры) и менять стоимость товара в зависимости от выбранных атрибутов (цвет, размер). Это невозможно реализовать стандартными настройками WooCommerce и требует доработок через код или плагины.
Пошаговое решение: как изменить цену в зависимости от роли пользователя и атрибутов товара
1. Определение роли пользователя в WooCommerce
Для начала нужно получить роль текущего пользователя в функции, которая будет изменять цену товара. Например:
function get_user_role() {
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
return (array) $user->roles;
}
return array('guest');
}2. Изменение цены товара по роли пользователя
Используем фильтр woocommerce_product_get_price и woocommerce_product_get_regular_price, чтобы изменить цену на лету:
add_filter('woocommerce_product_get_price', 'custom_price_by_role_and_attributes', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'custom_price_by_role_and_attributes', 10, 2);
function custom_price_by_role_and_attributes($price, $product) {
$roles = get_user_role();
// Проверяем роль
if (in_array('wholesaler', $roles)) {
// Оптовая скидка 20%
$price = $price * 0.8;
} elseif (in_array('vip_customer', $roles)) {
// VIP-клиенты - скидка 10%
$price = $price * 0.9;
}
// Дополнительно проверим атрибуты товара
$attributes = $product->get_attributes();
// Например, если цвет красный, добавим наценку 100 рублей
if (isset($attributes['pa_color'])) {
$color_terms = wc_get_product_terms($product->get_id(), 'pa_color', array('fields' => 'names'));
if (in_array('Red', $color_terms)) {
$price += 100;
}
}
return $price;
}3. Учет выбранных атрибутов вариативного товара
Для вариативных товаров цена зависит от вариации. Нужно использовать фильтр woocommerce_variation_prices_price для изменения цены вариации:
add_filter('woocommerce_variation_prices_price', 'custom_variation_price_by_role', 10, 3);
add_filter('woocommerce_variation_prices_regular_price', 'custom_variation_price_by_role', 10, 3);
function custom_variation_price_by_role($price, $variation, $product) {
$roles = get_user_role();
if (in_array('wholesaler', $roles)) {
$price = $price * 0.8;
} elseif (in_array('vip_customer', $roles)) {
$price = $price * 0.9;
}
// Можно добавить дополнительные проверки вариации
return $price;
}Проверка результата после внедрения
- Войдите под разными ролями пользователей (оптовик, VIP, гость) и проверьте цены товара на странице товара и в каталоге.
- Для вариативных товаров выберите разные атрибуты (цвет, размер) и проверьте изменение цены в зависимости от выбранной вариации.
- Используйте консоль браузера и инструменты разработчика, чтобы убедиться, что цена обновляется без ошибок JavaScript.
Частые ошибки и как их исправить
- Изменения цены не отображаются в корзине или на странице заказа. Нужно дополнительно изменить цену в корзине с помощью фильтра
woocommerce_before_calculate_totals. Пример:
add_action('woocommerce_before_calculate_totals', 'custom_price_cart_item', 10, 1);
function custom_price_cart_item($cart) {
if (is_admin() && !defined('DOING_AJAX'))
return;
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$roles = get_user_role();
$price = $product->get_price();
if (in_array('wholesaler', $roles)) {
$price = $price * 0.8;
} elseif (in_array('vip_customer', $roles)) {
$price = $price * 0.9;
}
$cart_item['data']->set_price($price);
}
}- Неверное определение ролей. Убедитесь, что роли пользователей существуют и правильно назначены. Для отладки используйте
error_log(print_r($roles, true)). - Цены не обновляются после смены атрибута на странице товара. Для вариативных товаров нужно корректно обработать JavaScript, который отвечает за обновление цены, либо использовать хуки WooCommerce.
Практические советы по безопасности и производительности
- Не кешируйте цены с учетом ролей пользователей, если используете серверное кеширование (например, Redis, Varnish). Кеш должен быть персонализирован по роли, иначе пользователи увидят чужие цены.
- Минимизируйте сложные вычисления в фильтрах цен, чтобы не замедлять загрузку страниц. Кешируйте результаты, если возможно.
- Для массовых изменений цен рассмотрите использование плагинов, которые поддерживают групповые скидки и динамические цены, например, «WooCommerce Dynamic Pricing» или «WooCommerce Role Based Pricing».
Сравнение вариантов реализации изменения цены в WooCommerce
| Метод | Плюсы | Минусы | Компромиссы |
|---|---|---|---|
| Код через хуки (фильтры) | Полный контроль, бесплатно, гибко | Требует навыков разработки, можно допустить ошибки | Необходимо тестировать и поддерживать |
| Плагины для динамического ценообразования | Простота настройки, поддержка, функционал | Стоимость, возможные конфликты, нагрузка | Удобно для бизнес-пользователей |
| Комбинация кода и плагинов | Оптимальный баланс, гибкость | Сложность поддержки | Использовать для сложных сайтов |