Универсальный список изнутри - инфоблок, поля и права
Разбираем универсальный список по слоям: в каком типе инфоблока он живёт и чем его поле отличается от свойства. Дальше смотрим, как считаются права на записи и что добавляет к списку поддержка бизнес-процессов.
Механика
Список - это инфоблок внутри отдельного типа, выделенного под списки проекта. Модуль хранит имя этого типа своей настройкой и показывает в разделе только его инфоблоки.
Тип инфоблока задают один раз, ещё до создания первого списка проекта. Инфоблок, заведённый в другом типе, в разделе списков не появится, хотя данные его целы и доступны кодом.
У нового списка ровно одно поле, и это его название. Остальные поля заводит человек, подбирая тип под характер данных из двенадцати доступных вариантов.
Поле списка - это свойство инфоблока вместе с надстройкой над ним. Интерфейс списка добавляет к свойству свои настройки: обязательность, множественность, показ, сортировку и режим только для чтения.
Код поля остаётся единственной стабильной опорой для всего кода проекта. Числовой идентификатор свойства выдаёт база, и на соседнем стенде у того же поля он будет другим.
Значения полей лежат в таблицах свойств того самого инфоблока, в котором живёт список. Вторая версия хранения держит их в отдельных таблицах инфоблока, но способ обращения к значениям от версии не зависит.
Сортировку полей интерфейс описывает правилом «чем выше число, тем ниже поле». На деле это обычная сортировка по возрастанию, просто названная от обратного, и путает она почти каждого.
Поддержку бизнес-процессов включают отдельным флагом в настройках самого списка. После этого запись списка становится документом, а документ задаётся тройкой из модуля, класса документа и идентификатора записи.
Права на список складываются из двух слоёв и работают только вместе. Модуль решает, кому доступен раздел списков и отведённый ему тип инфоблока, а сам список раздаёт уровни доступа к записям: чтение, изменение, добавление и документооборот.
Записи хранит инфоблок, поэтому доступ к ним считается его средствами. В расширенном режиме прав он считается по элементам и разделам, и устаревшая проверка прав инфоблока отвечает там неверно.
Шаги
- Посмотреть в настройках модуля списков, какой тип инфоблока отведён спискам проекта.
- Найти нужный список среди инфоблоков этого типа и запомнить его числовой идентификатор.
- Прочитать поля списка как свойства инфоблока и сверить их коды с ожиданиями кода проекта.
- Проверить уровни доступа групп на инфоблок списка и режим управления его правами.
- Убедиться, что флаг бизнес-процессов у списка отвечает тому, ради чего список заводили.
Код
Смотрим, какой тип инфоблока отдан спискам:
\Bitrix\Main\Loader::includeModule('lists');print_r(\Bitrix\Main\Config\Option::getForModule('lists'));// среди настроек модуля лежит тип инфоблока, отведённый спискам проекта// пустое значение означает, что раздел списков не к чему привязатьНастройка модуля живёт в базе, а не в файлах проекта. Поэтому на новом стенде её задают отдельно, до создания там первого рабочего списка.
Находим сам список среди инфоблоков этого типа:
$rows = \Bitrix\Iblock\IblockTable::getList([ 'filter' => ['=IBLOCK_TYPE_ID' => 'lists'], 'select' => ['ID', 'CODE', 'NAME', 'VERSION'],])->fetchAll();foreach ($rows as $row) { printf("%-5d %-16s %s версия=%d\n", $row['ID'], $row['CODE'], $row['NAME'], $row['VERSION']);}// VERSION показывает, как хранятся значения полей этого списка// CODE одинаков на стендах, а числовой идентификатор у каждого стенда свойВерсия хранения свойств определяет таблицы значений, а не способ обращения к ним. Вторая версия держит значения в отдельных таблицах инфоблока и выбирает их одним запросом без лишних соединений.
Читаем поля списка как свойства инфоблока:
$res = CIBlockProperty::GetList(['SORT' => 'ASC'], ['IBLOCK_ID' => $listIblockId]);while ($prop = $res->Fetch()) { printf("%-4d %-14s %s/%s сорт=%d\n", $prop['ID'], $prop['CODE'], $prop['PROPERTY_TYPE'], $prop['USER_TYPE'], $prop['SORT']);}// PROPERTY_TYPE: S строка, N число, L список, F файл, E элемент, G раздел// USER_TYPE уточняет базовый тип: HTML, Date, DateTime и другиеТип поля из интерфейса списка раскладывается на пару из базового и пользовательского типа свойства. Именно эта пара определяет форму ввода значения и способ фильтрации записей списка.
Заводим поле списка кодом:
$prop = new CIBlockProperty();$id = $prop->Add([ 'IBLOCK_ID' => $listIblockId, 'NAME' => 'Статус', 'CODE' => 'STATUS', 'PROPERTY_TYPE' => 'L', 'SORT' => 100, // меньше число - выше поле в форме 'VALUES' => [['VALUE' => 'новая'], ['VALUE' => 'в работе']],]);Код свойства обязателен при создании, и придумывают его один раз на всю жизнь списка. Без кода обращаться к полю придётся по числовому идентификатору, который перенос на другой стенд не переживает.
Читаем значения записи по кодам её полей:
$res = CIBlockElement::GetList([], ['IBLOCK_ID' => $listIblockId, 'ID' => $elementId], false, false, ['ID', 'NAME', 'PROPERTY_STATUS']);$row = $res->GetNext();printf("%s: %s\n", $row['NAME'], $row['PROPERTY_STATUS_VALUE']);// у списочного свойства приходит текст варианта, а номер лежит в PROPERTY_STATUS_ENUM_IDСмотрим уровни доступа групп к записям:
print_r(CIBlock::GetGroupPermissions($listIblockId)); // уровни доступа по группам// D доступа нет, R чтение, W изменение, X полный доступ вместе с правами// пустой ответ означает, что уровни на вкладке доступа списка не выданыПроверяем право на конкретную запись:
$can = CIBlockElementRights::UserHasRightTo($listIblockId, $elementId, 'element_read');var_dump($can); // проверка работает и в простом, и в расширенном режиме прав// устаревший CIBlock::GetPermission при расширенных правах отвечает неверноСмотрим процессы над записью списка:
if (\Bitrix\Main\Loader::includeModule('bizproc')) { print_r(CBPStateService::GetDocumentStates(['lists', 'BizprocDocument', $elementId]));}// запись списка приходит процессам документом из модуля, класса и номера записиПустой ответ у списка с включёнными процессами означает, что шаблоны ему не привязаны. Сам флаг только открывает такую привязку, а маршрут согласования рисуют отдельно в дизайнере процессов.
Ограничения
Модуля нет в младших редакциях: Старт, Стандарт и Малый бизнес. Закладывать списки в решение для этих редакций нельзя, и задачу там решают обычными инфоблоками.
Интерфейс списка выносит наружу не все настройки свойства инфоблока. Часть параметров правится только в карточке самого инфоблока, и это стоит учитывать при проектировании структуры.
Значение по умолчанию доступно только полю с включённым флагом обязательности. Поле, переведённое в режим только для чтения, не изменить и через форму самой записи списка.
Набор параметров поля зависит от выбранного типа и при смене типа перезагружается. Единого набора опций для всех двенадцати типов полей не существует, и проверять его приходится глазами.
Между стендами переносится структура списка, а не числовые идентификаторы его частей. Тип инфоблока, настройка модуля, поля с кодами и права групп задаются на боевом сайте заново.
Типичные проблемы
Готовый инфоблок подключили к списку, а его свойства в списке не видны.
Список ведёт своё описание полей поверх свойств инфоблока, и у чужого инфоблока его нет. Поля заводят через интерфейс списка, тогда описание появляется вместе со свойством.
Свой тип инфоблока не выбирается в источнике данных компонента списков.
В настройках модуля списков этому типу не выдан доступ, и компонент его не предлагает. Прямое указание типа в параметрах даёт ошибку прав вместо содержимого списка.
В таблице списка не видно колонок начиная со второй.
Настройка колонок ломается стилями главного грида на старом ядре платформы. Лечится обновлением ядра, а до обновления - правкой стиля окна настройки колонок.
Полю задали большое число сортировки, а оно ушло вниз формы.
Сортировка полей идёт по возрастанию, и большее число опускает поле ниже соседних. Формулировка интерфейса описывает то же правило от обратного и сбивает почти каждого.
Значение по умолчанию у поля не задаётся.
Оно доступно только полям с включённым флагом обязательности заполнения. Необязательному полю платформа задать значение по умолчанию не даёт вовсе.
Менеджер видит пустой список, а администратор видит все записи.
Права выданы на инфоблок, а сам инфоблок переведён в расширенный режим прав. В нём доступ считают по элементам и разделам, и проверяют его правами элемента.
Частые вопросы
Можно ли создать универсальный список на готовом инфоблоке?
Привязать инфоблок к списку получится, но своих полей у него не появится. Список ведёт описание полей поверх свойств, и заводят его через интерфейс списка.
Где хранятся данные элементов списка?
В таблицах свойств того самого инфоблока, в котором живёт список. Версия хранения решает, лежат значения в общей таблице или в отдельных таблицах инфоблока.
Чем поле списка отличается от свойства инфоблока?
Свойство хранит значения, а поле списка добавляет к нему настройки показа. Обязательность, множественность, сортировка и режим только для чтения задаются на стороне списка.
Как связать универсальный список с полем в бизнес-процессе?
Полем типа привязки к элементам, указав ему инфоблок нужного списка. Пустой выбор в таком поле означает, что записей в списке ещё нет.
Что из списка переносится между стендами?
Структура: тип инфоблока, сам список, поля с их кодами и права групп. Числовые идентификаторы и настройка модуля на новом стенде задаются заново.
Смежное
- Универсальные списки на практике - оглавление подтемы
- Универсальные списки - устройство модуля целиком
- Универсальный список: настройка, права и вывод элементов - как список заводят руками
- Список как справочник: поля, права, вывод и наполнение - когда список удобнее инфоблока
- Перенос универсального списка между стендами: структура, права, данные - что из устройства едет на бой
- Универсальный список не открывается или пуст: разбор причин - разбор неработающего раздела
- Бизнес-процесс над элементом списка: поля, раздел, PHP-код - процессы над записями списка
- Инфоблоки - хранилище под всеми списками
- Права на инфоблок и заказы: выдача из интерфейса и кодом - уровни доступа и режимы прав
- Highload-блоки - куда выносить большие справочники
- Поля универсального списка - какой тип поля что даёт и что задаётся при создании