WooCommerce: автоматическое изменение стоимости товара в зависимости от роли пользователя

Диагностика задачи: зачем менять цену в зависимости от роли

В интернет-магазинах на WooCommerce часто требуется показывать разные цены для разных групп пользователей — например, оптовым покупателям, дистрибьюторам или зарегистрированным клиентам с особым статусом. Стандартный функционал WooCommerce не предусматривает такой кастомизации цен, поэтому приходится внедрять собственные решения с помощью кода или плагинов.

Пошаговое решение: как реализовать динамическую цену по ролям

1. Определяем роли пользователей

Убедитесь, что у вас есть роли, для которых нужно менять цены. Например, wholesale_customer — оптовый покупатель, vip_customer — клиент с VIP статусом и так далее. Роли можно создавать вручную или через плагины типа User Role Editor.

2. Добавляем фильтр для изменения цены товара

WooCommerce позволяет менять цену с помощью фильтра woocommerce_get_price. Ниже пример кода, который меняет цену товара в зависимости от роли пользователя:

add_filter('woocommerce_get_price', 'change_price_by_user_role', 10, 2);
function change_price_by_user_role($price, $product) {
    if (is_admin() && !defined('DOING_AJAX')) {
        return $price; // не меняем в админке
    }

    if (!is_user_logged_in()) {
        return $price; // для гостей возвращаем стандартную цену
    }

    $user = wp_get_current_user();

    if (in_array('wholesale_customer', $user->roles)) {
        // Скидка 20% для оптовиков
        $price = $price * 0.8;
    } elseif (in_array('vip_customer', $user->roles)) {
        // Фиксированная цена для VIP
        $vip_prices = array(
            123 => 50, // ID товара => цена
            456 => 80,
        );
        $product_id = $product->get_id();
        if (isset($vip_prices[$product_id])) {
            $price = $vip_prices[$product_id];
        }
    }

    return $price;
}

3. Кеширование и производительность

Обратите внимание, что подобные фильтры влияют на скорость загрузки страниц, особенно если цены зависят от сложной логики. Можно кешировать результаты для авторизованных пользователей с помощью transient API или плагинов кеширования, поддерживающих динамические фрагменты.

Проверка результата после внедрения

  • Залогиньтесь под пользователем с ролью wholesale_customer и проверьте цену товара — она должна быть на 20% ниже.
  • Залогиньтесь под пользователем с ролью vip_customer и убедитесь, что для товаров с ID 123 и 456 цена фиксированная.
  • Проверьте, что для гостей и других ролей цена не изменилась.
  • Проверьте работу на странице корзины и оформления заказа, чтобы убедиться, что цена корректно применяется во всех местах.

Частые ошибки и как их исправить

  • Изменение цены только на фронтенде, а не в корзине/чекауте. Фильтр woocommerce_get_price влияет только на вывод, для корректного изменения цены в корзине используйте фильтр woocommerce_before_calculate_totals и изменяйте цену товара в объекте WC_Cart_Item.
  • Цена не меняется для вариативных товаров. Для вариативных товаров надо обрабатывать объекты типа WC_Product_Variation отдельно, проверяя ID вариации.
  • Проблемы с кешем и кеширующими плагинами. Отключите кеширование для страниц с ценами, меняющимися по ролям, или используйте динамические фрагменты.

Практические советы по безопасности и производительности

  • Не используйте глобальные переменные и не делайте запросы к базе в фильтрах цен без кеширования — это замедлит сайт.
  • Для сложных правил ценообразования рассмотрите использование готовых плагинов с поддержкой ролей, например, Clearfy Pro может помочь с оптимизацией и SEO, но для цен лучше кастомные решения.
  • Проверяйте сайт на предмет утечек информации: не показывайте оптовые цены гостям и пользователям без нужной роли.

Пример расширения: корректная замена цены в корзине

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();

    foreach ($cart->get_cart() as $cart_item) {
        $product = $cart_item['data'];
        $original_price = $product->get_regular_price();

        if (in_array('wholesale_customer', $user->roles)) {
            $new_price = $original_price * 0.8;
            $product->set_price($new_price);
        } elseif (in_array('vip_customer', $user->roles)) {
            $vip_prices = array(
                123 => 50,
                456 => 80,
            );
            $product_id = $product->get_id();
            if (isset($vip_prices[$product_id])) {
                $product->set_price($vip_prices[$product_id]);
            }
        } else {
            $product->set_price($original_price);
        }
    }
}
WooCommerce: как отключить возможность повторного добавления товара в корзину
25.05.2026
Как отладить проблемы с отображением визуального редактора Gutenberg в WordPress
27.11.2025
Автоматическое удаление неактивных пользователей WordPress: практические решения
12.04.2026
Как отключить автоматический выход из WordPress
17.02.2026
Как создать собственный виджет для WordPress
14.11.2025