Перейти к содержимому

Пользовательское поле - заведение, вывод значения, типы

Заводим пользовательское поле у нужной сущности, читаем его значение и разбираемся, почему оно не появляется в форме.

Решение

Смотрим, какие поля уже заведены у сущности:

$fields = CUserTypeEntity::GetList([], ['ENTITY_ID' => 'USER']);
while ($field = $fields->Fetch()) {
printf("%-24s %-14s множ=%s обяз=%s\n",
$field['FIELD_NAME'], $field['USER_TYPE_ID'],
$field['MULTIPLE'], $field['MANDATORY']);
}

Идентификатор сущности у каждой свой: USER для пользователя, IBLOCK_<id>_SECTION для разделов инфоблока, ORDER для заказа. Поле, заведённое не у той сущности, в нужной форме не появится никогда.

Заводим поле:

$entity = new CUserTypeEntity();
$entity->Add([
'ENTITY_ID' => 'USER',
'FIELD_NAME' => 'UF_DEPARTMENT_CODE', // префикс UF_ обязателен
'USER_TYPE_ID' => 'string', // тип потом не меняется
'MULTIPLE' => 'N',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => ['ru' => 'Код подразделения'],
]);

Подпись задаётся отдельно для каждого языка. Без неё поле показывается системным именем, и в форме появляется строка UF_DEPARTMENT_CODE вместо человеческого названия.

Читаем значение поля:

global $USER_FIELD_MANAGER;
$values = $USER_FIELD_MANAGER->GetUserFields('USER', $userId, LANGUAGE_ID);
echo $values['UF_DEPARTMENT_CODE']['VALUE'] ?? '-', "\n";

Менеджер отдаёт не только значение, но и описание поля: тип, подпись, множественность. Прямая выборка из таблицы вернёт голое значение и потребует разбирать тип самому.

Записываем значение:

$user = new CUser();
$user->Update($userId, ['UF_DEPARTMENT_CODE' => 'IT-01']);
// у множественного поля передаётся массив, у одиночного - скаляр

Запись идёт через API самой сущности, а не через менеджер полей. У пользователя это CUser::Update, у раздела - CIBlockSection::Update, и так далее.

Выбираем сущности по значению поля:

$users = CUser::GetList('ID', 'ASC', ['UF_DEPARTMENT_CODE' => 'IT-01'],
['SELECT' => ['UF_DEPARTMENT_CODE'], 'FIELDS' => ['ID', 'LOGIN']]);
while ($row = $users->Fetch()) {
printf("%-6s %-20s %s\n", $row['ID'], $row['LOGIN'], $row['UF_DEPARTMENT_CODE']);
}

Поле надо назвать и в фильтре, и в списке выбираемых: без второго значение в результат не попадёт, хотя фильтр отработает.

Выводим поле типа «файл»:

$fileId = $values['UF_SCAN']['VALUE']; // в значении лежит идентификатор
if ($fileId) {
echo CFile::GetPath($fileId); // путь получаем отдельным вызовом
}

В значении хранится идентификатор файла, а не путь к нему. У множественного поля там массив идентификаторов, и каждый разворачивается в путь отдельно.

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

Типичные проблемы

Поле заведено, но в форме его нет.

Оно привязано к другой сущности. Идентификаторы у пользователя, раздела и заказа разные, и поле показывается только в форме своей сущности.

Вместо подписи в форме системное имя поля.

Не заполнена подпись для текущего языка. Подписи задаются отдельно на каждый язык, и без нужного показывается имя поля.

Тип поля выбран неверно, а поменять нельзя.

Тип задаётся при создании и не меняется: значения хранятся в разных форматах. Заводят новое поле и переносят значения своим кодом.

Из нескольких значений сохранилось одно.

У поля снят флаг множественности. Массив принимается без ошибки, но в базу уходит последний элемент.

В поле знаки вопроса вместо русского текста.

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

Частые вопросы

Как получить список сущностей, к которым можно крепить поля?

Каждый модуль объявляет свои сущности сам, единого списка нет. Практический способ - посмотреть, какие значения ENTITY_ID уже встречаются в справочнике полей на этом проекте.

Можно ли выбрать пользователей по значению поля?

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

Чем поле типа «список» отличается от «расширенного списка»?

Первый хранит идентификатор значения из своего справочника. Второй берёт значения из highload-блока и годится, когда справочник большой и им управляют отдельно.

Как вывести поле типа «файл»?

В значении лежит идентификатор файла, а не путь. Путь получают отдельным вызовом по этому идентификатору, а у множественного поля обходят массив.

Смежное

Первоисточник