Заметки
Как передать массив в итератор БП
Как подготовить множественную переменную для итератора бизнес-процесса: преобразовать строку, JSON или результат REST в массив значений.
Итератор работает не с произвольной строкой, а с множественной переменной БП. Если из REST или PHP-активити пришёл JSON, строка через запятую или многострочный текст, сначала нужно превратить это в массив, записать в множественную переменную и уже её выбрать в настройках итератора.
Задача
В бизнес-процессе часто нужно пройтись по списку значений: ID сделок, элементов смарт-процесса, пользователей, строк из внешней системы или результатам REST-запроса.
Для этого в БП есть конструкция «Итератор». Она берёт множественную переменную и выполняет вложенные действия для каждого значения из этой переменной.
Проблема появляется, когда список приходит не как готовая множественная переменная, а как строка:
101, 102, 103;- многострочный текст;
- JSON-массив;
- ответ REST с массивом внутри
result; - строка, которую вернула PHP-активити или внешняя система.
В таком виде отдавать данные в итератор не стоит. Сначала нужно подготовить массив и записать его в переменную БП, которая настроена как множественная.
Что ждёт итератор
Итератору нужна переменная, в которой лежит несколько отдельных значений.
Обычно для этого заранее создают переменную БП, например IteratorItems,
и включают у неё множественность.
В PHP-активити такую переменную можно заполнить массивом:
$items = [
101,
102,
103,
];
$this->SetVariable('IteratorItems', $items);
После этого в настройках итератора выбирается переменная IteratorItems.
Внутри итератора каждое действие будет работать с очередным значением.
Важно не путать массив и строку, которая внешне похожа на массив:
$this->SetVariable('IteratorItems', '[101,102,103]'); Это строка. Для итератора нужен не такой текст, а реальные отдельные значения:
$this->SetVariable('IteratorItems', [
101,
102,
103,
]);
Поэтому основная работа перед итератором — привести входные данные к массиву и записать
его в множественную переменную через SetVariable.
Строка с разделителями
Самый частый вариант — список приходит строкой через запятую, точку с запятой или переносы строк. Так бывает после ручного ввода, REST-активити, внешнего обработчика или старого PHP-действия.
Если значения разделены запятыми:
$source = '101, 102, 103';
$items = preg_split('/[,;\n\r]+/', $source);
$items = array_map('trim', $items);
$items = array_filter($items, static function ($item): bool {
return $item !== '';
});
$this->SetVariable('IteratorItems', array_values($items));
Здесь строка разбивается по запятым, точкам с запятой и переносам строк. Потом у каждого
элемента убираются пробелы, пустые значения отбрасываются, а результат записывается
в IteratorItems.
Для многострочного текста можно оставить только разбор переносов:
$source = trim((string)$this->GetRootActivity()->GetVariable('SourceText'));
$items = preg_split('/\r\n|\r|\n/', $source);
$items = array_map('trim', $items);
$items = array_filter($items, static function ($item): bool {
return $item !== '';
});
$this->SetVariable('IteratorItems', array_values($items)); Такой вариант удобен, если пользователь вставляет список значений в многострочную переменную: каждый ID или код на отдельной строке.
JSON из REST или PHP-активити
Если список пришёл как JSON, его нужно декодировать через json_decode.
Нельзя просто записать JSON-строку в множественную переменную и ждать, что итератор
сам разберёт её на элементы.
Простой JSON-массив:
$json = '[101, 102, 103]';
$items = json_decode($json, true);
if (!is_array($items)) {
$items = [];
}
$items = array_values(array_filter($items, static function ($item): bool {
return $item !== null && $item !== '';
}));
$this->SetVariable('IteratorItems', $items);
Иногда внешний обработчик или REST-ответ возвращает не сам массив, а объект с ключом
result:
$json = '{"result":[101,102,103]}';
$data = json_decode($json, true);
$items = [];
if (is_array($data) && isset($data['result']) && is_array($data['result'])) {
$items = $data['result'];
}
$this->SetVariable('IteratorItems', array_values($items)); Если источник может быть разным — массив, JSON, строка через запятую или пустое значение — удобнее сделать одну функцию нормализации:
function normalizeIteratorItems(mixed $value): array
{
if ($value === null || $value === '') {
return [];
}
if (is_array($value)) {
return array_values(array_filter($value, static function ($item): bool {
return $item !== null && $item !== '';
}));
}
$string_value = trim((string)$value);
if ($string_value === '') {
return [];
}
$decoded_value = json_decode($string_value, true);
if (json_last_error() === JSON_ERROR_NONE) {
if (is_array($decoded_value)) {
if (isset($decoded_value['result']) && is_array($decoded_value['result'])) {
return normalizeIteratorItems($decoded_value['result']);
}
return normalizeIteratorItems($decoded_value);
}
return [$decoded_value];
}
$items = preg_split('/[,;\n\r]+/', $string_value);
$items = array_map('trim', $items);
$items = array_filter($items, static function ($item): bool {
return $item !== '';
});
return array_values($items);
}
$root_activity = $this->GetRootActivity();
$source_value = $root_activity->GetVariable('SourceValue');
$iterator_items = normalizeIteratorItems($source_value);
$this->SetVariable('IteratorItems', $iterator_items); Такой код хорошо подходит для PHP-активити перед итератором. На вход можно передать значение из переменной БП, строку из REST-действия или уже готовый массив. На выходе получится обычный массив для множественной переменной.
Пользователи и другие типы
Тип переменной важен. Если итератор должен проходить по строкам, создавайте множественную строковую переменную. Если по числам — числовую. Если по пользователям — переменную типа «Пользователь».
Для пользователей часто нужен формат user_ID, а не просто число.
Например:
$user_ids = [
1,
2,
3,
];
$user_values = [];
foreach ($user_ids as $user_id) {
$user_id = (int)$user_id;
if ($user_id > 0) {
$user_values[] = 'user_' . $user_id;
}
}
$this->SetVariable('IteratorUsers', $user_values);
Такой массив можно записать в множественную переменную типа «Пользователь» и потом
использовать её в итераторе или других действиях БП. В справке Bitrix24 для PHP-кода
тоже используется массив пользователей в формате user_1 и
user_2.
Для списков и пользовательских полей важно передавать не красивое название значения,
а тот формат, который ожидает переменная или следующее действие. Иногда это ID пункта,
иногда строковый код, иногда значение вида user_5.
Главное правило простое: итератор не должен заниматься разбором строки. Перед ним лучше поставить отдельное PHP-действие, которое нормализует входные данные и записывает чистый массив в множественную переменную. Тогда сам итератор остаётся простым и предсказуемым.