Разберём задачу по реализации разграничения видимости товаров на основе свойства инфоблока FOR_MEMBERS_ONLY.
Варианты реализации
Есть несколько подходов. Рассмотрим два основных.
Способ 1. Модификация выборки через событие OnBeforeCIBlockElementGetList
Самый гибкий способ — перехватить запрос к элементам инфоблока каталога и добавить условие фильтрации по свойству FOR_MEMBERS_ONLY в зависимости от группы пользователя.
Вам нужно создать обработчик события в файле init.php (или в своём модуле):
use \Bitrix\Main\EventManager;
use \Bitrix\Main\GroupTable;
use \Bitrix\Main\UserTable;
// ID группы "Участники" — укажите свой
define('MEMBERS_GROUP_ID', 5);
EventManager::getInstance()->addEventHandler(
'iblock',
'OnBeforeCIBlockElementGetList',
'onBeforeCIBlockElementGetListHandler'
);
function onBeforeCIBlockElementGetListHandler(&$arOrder, &$arFilter, &$arGroupBy, &$arNavStartParams, &$arSelectFields)
{
// Проверяем, работает ли в административной части — не трогаем
if (defined('ADMIN_SECTION') && ADMIN_SECTION === true) {
return;
}
global $USER;
// Если пользователь не авторизован — ничего не меняем
if (!$USER || !$USER->IsAuthorized()) {
return;
}
// Проверяем, состоит ли пользователь в группе "Участники"
$userGroups = $USER->GetUserGroupArray();
if (in_array(MEMBERS_GROUP_ID, $userGroups)) {
// Участники видят ВСЕ товары — не добавляем фильтр
return;
}
// Для обычных зарегистрированных пользователей
// Добавляем фильтр: только товары, у которых FOR_MEMBERS_ONLY != Y
$arFilter['!PROPERTY_FOR_MEMBERS_ONLY_VALUE'] = 'Y';
}
Что это даёт:
- Если пользователь — участник (группа ID = MEMBERS_GROUP_ID) — фильтр НЕ добавляется, он видит все товары.
- Если обычный зарегистрированный — добавляется условие
!PROPERTY_FOR_MEMBERS_ONLY_VALUE = 'Y', т.е. исключаются товары со свойством FOR_MEMBERS_ONLY = Y. - Неавторизованные — поведение по умолчанию (можно доработать под свои нужды).
Способ 2. Модификация через CIBlockElement::GetList в комплексном компоненте каталога
Если вы используете типовой компонент bitrix:catalog, можно переопределить его параметры через params.php или передать кастомный фильтр через arParams['CUSTOM_FILTER'].
Однако в стандартном bitrix:catalog такого параметра нет. Проще использовать событие OnBeforeCIBlockElementGetList, как описано выше.
Способ 3. Кастомный компонент вывода списка товаров
Если вы пишете свой компонент:
global $USER;
$arFilter = [
'IBLOCK_ID' => CATALOG_IBLOCK_ID,
'ACTIVE' => 'Y',
];
// Если пользователь НЕ участник — скрываем товары для участников
if (!$USER->IsAuthorized() || !in_array(MEMBERS_GROUP_ID, $USER->GetUserGroupArray())) {
$arFilter['!PROPERTY_FOR_MEMBERS_ONLY_VALUE'] = 'Y';
}
$rsElements = CIBlockElement::GetList(
['SORT' => 'ASC'],
$arFilter,
false,
false,
['ID', 'NAME', 'PROPERTY_FOR_MEMBERS_ONLY']
);
Что нужно сделать дополнительно:
- Создайте группу пользователей «Участники» (Админка → Настройки → Пользователи → Группы пользователей) и запишите её ID.
- Добавьте свойство инфоблока «FOR_MEMBERS_ONLY» (тип «Список», значения Y/N).
- Разместите код в
/bitrix/php_interface/init.phpили лучше в своём кастомном модуле. - Проверьте кеш — если используется композитный кеш, результат может кешироваться для разных пользователей некорректно. Рекомендуется отключить кеширование для этого компонента или использовать автокомпозитный кеш с привязкой к группам пользователей.
Важное замечание про кеширование
Если стандартные компоненты кешируются, фильтр из события OnBeforeCIBlockElementGetList может не отработать, так как данные будут взяты из кеша. Чтобы этого избежать:
- Установите для компонента каталога параметр CACHE_TYPE = "N" (отключить кеш) — не рекомендуется для высоконагруженных проектов.
- Либо используйте собственный компонент с управлением кешем через теги, привязанные к группам пользователей.
Альтернатива — права доступа к элементам инфоблока
В Битриксе есть встроенный механизм разграничения прав на элементы инфоблока (Права на доступ к элементам инфоблока). Но он менее гибкий для вашей задачи. Свойство FOR_MEMBERS_ONLY с фильтрацией через событие — более простой и прозрачный способ.