Проблема: необходимость скрыть категории товаров для определённых ролей пользователей в WooCommerce
В стандартном WooCommerce нет встроенного механизма для ограничения видимости категорий товаров в каталоге и на страницах магазина в зависимости от роли пользователя. Это часто необходимо, например, при создании B2B-сайтов, где оптовые товары должны быть видны только оптовым клиентам, а розничные — остальным.
Диагностика проблемы
Чтобы убедиться, что WooCommerce не скрывает категории по ролям, проверьте следующие моменты:
- Наличие плагинов для ограничения доступа или каталога, которые могли бы влиять на отображение товаров.
- Проверка, показываются ли все товары и категории для всех пользователей, включая гостевых.
- Отсутствие кастомных фильтров в файлах темы или плагинах, которые могли бы изменять запросы WooCommerce.
Пошаговое решение: исключение категорий товаров по ролям пользователей
Реализуем исключение категорий товаров из каталога и поиска WooCommerce с помощью фильтра woocommerce_product_query. Пример кода помещается в файл functions.php вашей дочерней темы или в кастомный плагин.
add_action('woocommerce_product_query', 'exclude_categories_by_user_role', 10, 2); function exclude_categories_by_user_role($query, $query_vars) { if (is_admin() || !is_shop() && !is_product_category() && !is_product_tag()) { return; } $user = wp_get_current_user(); $restricted_categories = array(); if (in_array('wholesale_customer', (array) $user->roles)) { // Для оптовых клиентов показываем только определённые категории // Здесь исключаем розничные категории $restricted_categories = array('retail'); } elseif (in_array('customer', (array) $user->roles)) { // Для розничных клиентов скрываем оптовые категории $restricted_categories = array('wholesale'); } if (!empty($restricted_categories)) { $tax_query = (array) $query->get('tax_query'); $tax_query[] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $restricted_categories, 'operator' => 'NOT IN', ); $query->set('tax_query', $tax_query); } }Пояснения:
woocommerce_product_query— хук для изменения WP_Query товаров.- Проверяем контекст (админка, магазин, категории, теги).
- Определяем роли пользователя и задаём категории, которые нужно исключить.
- Добавляем в запрос таксономический фильтр, исключающий выбранные категории.
Дополнительная настройка: исключение категорий в виджетах и видимости
По умолчанию этот подход не исключит товары из виджетов и других запросов WooCommerce. Для полноты можно добавить фильтр на pre_get_posts с аналогичной логикой.
add_action('pre_get_posts', 'exclude_categories_from_widgets_by_role'); function exclude_categories_from_widgets_by_role($query) { if (is_admin() || !$query->is_main_query()) { return; } if ($query->is_post_type_archive('product') || $query->is_tax('product_cat') || $query->is_tax('product_tag')) { $user = wp_get_current_user(); $restricted_categories = array(); if (in_array('wholesale_customer', (array) $user->roles)) { $restricted_categories = array('retail'); } elseif (in_array('customer', (array) $user->roles)) { $restricted_categories = array('wholesale'); } if (!empty($restricted_categories)) { $tax_query = (array) $query->get('tax_query'); $tax_query[] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $restricted_categories, 'operator' => 'NOT IN', ); $query->set('tax_query', $tax_query); } } }Проверка результата после внедрения
- Выйдите из админки и зайдите на сайт под разными ролями (например, используя плагин User Switching).
- Перейдите на страницу магазина и категории товаров, проверьте, что запрещённые категории не отображаются в списках.
- Убедитесь, что товары из исключённых категорий полностью отсутствуют в каталоге и поиске.
- Проверьте, что в админке администраторы видят все товары без ограничений.
Частые ошибки и как их исправить
- Код не работает, категория не скрывается: проверьте правильность слагов категорий, они должны совпадать с теми, что в WooCommerce (в разделе Товары → Категории).
- Фильтр не срабатывает на страницах виджетов или других кастомных запросах: добавьте аналогичный фильтр на
pre_get_postsс проверкой условий. - Роли пользователей определены неверно: убедитесь, что роли точно совпадают с теми, что указаны в базе, используйте
print_r(wp_get_current_user()->roles)для отладки. - Пользователь видит товары из запрещённой категории после кэширования: очистите кэш сайта и браузера, проверьте работу с отключённым кэшем.
Практические советы по безопасности и производительности
- Не используйте жёстко прописанные слаги категорий — лучше вынести их в настройки или константы для удобного управления.
- Для больших каталогов с тысячами товаров и категорий рассмотрите использование транзиентов или кэширующих механизмов для снижения нагрузки на запросы с tax_query.
- Избегайте выполнения фильтра на страницах админки, чтобы не влиять на работу админ-панели.
- Если у вас много ролей и сложная логика, лучше реализовать отдельный класс или сервис, инкапсулирующий правила видимости.
Сравнение вариантов реализации ограничения видимости категорий
| Способ | Плюсы | Минусы |
|---|---|---|
Использование woocommerce_product_query | Простой и нативный метод, работает на странице магазина и категории | Не покрывает все запросы WooCommerce, требует дополнительных фильтров |
Фильтр pre_get_posts | Работает на всех WP_Query, охватывает виджеты и архивы | Можно случайно затронуть другие запросы, нужно аккуратно задавать условия |
| Плагины для ограничения каталога (например, WooCommerce Catalog Visibility Options) | Готовое решение с GUI, простая настройка | Платные, могут добавлять нагрузку, меньше гибкости, чем код |