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

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

В интернет-магазинах на WooCommerce часто возникает задача показывать определённые товары только определённым группам пользователей — например, оптовым покупателям или зарегистрированным клиентам с ролью "дилер". Это помогает реализовать дифференцированное ценовое предложение и персонализацию каталога.

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

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

1. Определение ролей и продуктов

Для начала определимся с ролями пользователей. Можно использовать стандартные роли WordPress или добавить свои. Например, роль wholesale_customer для оптовых клиентов.

2. Скрытие продуктов от неавторизованных ролей

Добавим фильтр, который исключит из каталога продукты, если пользователь не принадлежит к разрешённой роли.

add_action('pre_get_posts', 'wpa_restrict_products_by_role');
function wpa_restrict_products_by_role($query) {
    if (is_admin() || !$query->is_main_query()) {
        return;
    }
    if (is_shop() || is_product_category() || is_product_tag()) {
        $user = wp_get_current_user();
        $allowed_roles = ['wholesale_customer', 'administrator']; // роли с доступом
        if (!array_intersect($allowed_roles, (array) $user->roles)) {
            // Исключаем продукты с мета key 'restricted' = 'yes'
            $meta_query = $query->get('meta_query');
            if (!$meta_query) {
                $meta_query = [];
            }
            $meta_query[] = [
                'key' => 'restricted',
                'value' => 'yes',
                'compare' => '!=',
            ];
            $query->set('meta_query', $meta_query);
        }
    }
}

В данном примере мы предполагаем, что у товаров, доступ к которым надо ограничить, есть метаполе restricted со значением yes.

3. Добавление метаполя к продуктам

Чтобы пометить нужные продукты, можно использовать стандартный UI WooCommerce (через кастомные поля) или добавить метабокс через код:

add_action('add_meta_boxes', function() {
    add_meta_box('product_restricted', 'Ограниченный доступ', function($post) {
        $value = get_post_meta($post->ID, 'restricted', true);
        wp_nonce_field('save_restricted_meta', 'restricted_meta_nonce');
        ?>
        <label><input type="checkbox" name="restricted" value="yes" <?php checked($value, 'yes'); ?>> Ограничить доступ</label>
        <?php
    }, 'product', 'side');
});

add_action('save_post_product', function($post_id) {
    if (!isset($_POST['restricted_meta_nonce']) || !wp_verify_nonce($_POST['restricted_meta_nonce'], 'save_restricted_meta')) {
        return;
    }
    $restricted = isset($_POST['restricted']) && $_POST['restricted'] === 'yes' ? 'yes' : '';
    update_post_meta($post_id, 'restricted', $restricted);
});

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

  • Залогиньтесь под пользователем с ролью wholesale_customer — в каталоге должны отображаться все товары, включая помеченные как ограниченные.
  • Залогиньтесь под пользователем без этой роли — ограничённые товары должны исчезнуть из каталога и поисковой выдачи.
  • Проверьте, что ограниченные товары недоступны через прямую ссылку — для этого дополнительно нужно реализовать проверку при загрузке продукта.

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

add_action('template_redirect', function() {
    if (is_product()) {
        global $post;
        $user = wp_get_current_user();
        $allowed_roles = ['wholesale_customer', 'administrator'];
        $restricted = get_post_meta($post->ID, 'restricted', true);
        if ($restricted === 'yes' && !array_intersect($allowed_roles, (array) $user->roles)) {
            wp_redirect(home_url());
            exit;
        }
    }
});

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

  • Ошибка: Ограниченные продукты всё равно видны для неавторизованных пользователей.
    Причина: Фильтр pre_get_posts не срабатывает, если запрос не основной или код подключён не в правильном хукe.
    Решение: Убедитесь, что функция подключена к pre_get_posts и проверяется $query->is_main_query(). Код должен быть в файле темы functions.php или в плагине.
  • Ошибка: Ограниченные продукты доступны по прямой ссылке.
    Причина: Нет проверки доступа на уровне шаблона продукта.
    Решение: Добавьте редирект в template_redirect, как показано выше.
  • Ошибка: Метаполе restricted не сохраняется или не отображается.
    Причина: Нет nonce-проверки или неправильно реализена сохранение метаполя.
    Решение: Следуйте примеру с nonce и проверкой прав в функции сохранения метаполя.

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

  • Используйте проверки nonce и capability при сохранении метаполей, чтобы предотвратить CSRF и несанкционированное изменение данных.
  • Для больших каталогов с множеством ограниченных продуктов рекомендуется индексировать метаполя в базе данных для ускорения запросов.
  • Если ограничений много, рассмотрите использование специализированных плагинов (например, «Members» или «User Role Editor») для упрощения управления ролями.
  • Кэширование страниц с учётом ролей пользователей может привести к утечке ограниченного контента — используйте кэширование, учитывающее текущего пользователя или отключайте кэш для страниц каталога.

Сравнение вариантов реализации ограничения доступа

МетодПлюсыМинусы
Код на pre_get_posts + метаполеПолный контроль, бесплатно, легко кастомизируетсяТребует знаний PHP, возможны ошибки при реализации
Плагин «Members» или «Groups»Удобный UI, гибкие настройки ролей и доступаДополнительная нагрузка, не всегда подходит для тонкой настройки товаров
Платные решения WooCommerce MembershipsПолный функционал, поддержка, интеграция с WooCommerceЦена, избыточность для простых задач
Ограничение количества попыток входа в WordPress: создание кастомного плагина
03.01.2026
WooCommerce: автоматическое удаление пользователя при отмене подписки
20.05.2026
WordPress авторизация по IP адресу: настройка и примеры кода
21.01.2026
WooCommerce: как реализовать авторизацию через OTP без SMS-провайдеров
13.06.2026
WordPress REST API: создание кастомной аутентификации по токену
25.01.2026