Допустим, вы прочитали инструкции тут и тут. Создали свой высоконагруженный инфоблок (по сути – почти обычную таблицу) и у вас в этом highload-блоке есть поле, в котором хранится привязка сущностей этого блока к ID элементов старых добрых инфоблоков. Поле это будет целочисленным и множественным и необязательным.
Чтобы общаться с этой таблицей, мы в каком-нибудь модуле опишем класс в папке lib. В этом классе будет метод getMap, который опишет все поля, которые мы создали в таблице.
Описание проблемы
Теперь мы попробуем создать запись в таблице вот примерно так
\ПространствоИмён\ИмяКласса::Add([
//упустим остальные параметры
'ИМЯ_МНОЖЕСТВЕННОГО_ПОЛЯ' => [
123123,
324234
]
])
Запись может пройти все проверки (вы ведь описали Valdator для каждого поля в карте (метод getMap)?), но в интерфейсе админки битрикса, при просмотре данных в инфоблоке никаких значений во множественном поле не будет.
Вызов
ИмяКласса::getList()->fetchAll()
вернёт все наши записи. И во множественном поле тут также будет пусто. Возможна еще такая ситуация, когда мы передаём только один ID
\ПространствоИмён\ИмяКласса::Add([
//упустим остальные параметры
'ИМЯ_МНОЖЕСТВЕННОГО_ПОЛЯ' => 3213123
])
В этом случае в админке будет пусто, но getList вернёт нам значение этого поля. В чем же подвох?
Решение проблемы
Тут всё просто — множественные поля должны сериализовываться. Странно, что в документации этого нет. Можно сильно упростить себе жизнь, описав грамотную карту таблицы. Например, если указать в описании поля параметр ‘serialized’ => true, то битрикс сам будет сериализовывать все данные перед сохранением в таблицу и при возврате. С этим параметром и в админке и в коде всё будет отображаться нормально.
НО! Возникает проблема – если ID у нас в одном экзепляре, то хотелось бы передать только его, не засовывая в массив. Но при этом, чтобы возвращался в коде всегда массив, даже если там только одно значение, чтобы не проверят каждый раз тип данных. В этом нам поможет параметр ‘save_data_modification’, который может принудительно запихнут число в массив.
Получается, что поле в методе getMap должно быть описано примерно так.
new Entity\IntegerField('ИМЯ_МНОЖЕСТВЕННОГО_ПОЛЯ', [
'column_name' => 'UF_ИМЯ_МНОЖЕСТВЕННОГО_ПОЛЯ',
'serialized' => true,
//принудительно сохраняем данные в массив
'save_data_modification' => function(){
return [
function($value){
if(!is_array($value)){
return [$value];
}else{
return $value;
}
}
];
},
'validation' => function() {
return [
function($value){
if(is_array($value)){
$result = true;
foreach($value as $item){
if(!(is_numeric($item) and intval($item) > 0)){
$result = false;
}
}
if($result){
return $result;
}else{
return 'Некорректный массив с ID элементов';
}
}elseif(is_numeric($value) and intval($value) > 0){
return true;
}else{
return 'Некорректный ID элемента, ожидается целое число или
массив целых чисел.';
}
}
];
}
]),
И тогда всё будет удобно и красиво =)
P.S.
очень жаль, что у вас вырезаются все пустые строки — без этого текст становится нечитаемым.
добавьте пожалуйста разрывы на абазацы, как в оригинальном сообщении
Ответить
Добавил отступ снизу у параграфов, стало лучше читаться.
Ответить