Перенос универсального списка между стендами - структура, права, данные
Переносим универсальный список с разработки на боевой сайт: структуру, коды полей, права сотрудников и сами записи.
Что нужно знать заранее
Универсальный список - это инфоблок особого типа. Значит, и переносится он теми же средствами, что и обычный инфоблок: миграцией, а не выгрузкой файлов проекта.
Числовые идентификаторы полей на разных стендах проекта не совпадают почти никогда. Код, который обращается к полю по номеру, ломается сразу после переноса, поэтому каждому полю задают понятный буквенный код.
Записи списка - это данные проекта, а структурой считается только сам список с полями. Их переносят отдельным шагом и сопоставляют по внешнему коду, иначе повторный запуск заведёт вторые копии записей.
Шаги
- Задать всем полям списка понятные буквенные коды ещё на стенде разработки.
- Написать миграцию, создающую сам список и все его поля по заранее заданным кодам.
- Повторить в миграции права всех групп на просмотр и на правку записей списка.
- Залить записи отдельным шагом выкладки, сопоставляя их по внешнему коду системы-источника.
- Проверить готовый список под учётной записью обычного сотрудника, а не под администратором.
Решение
Находим список среди инфоблоков:
$rows = \Bitrix\Iblock\IblockTable::getList(['filter' => ['=IBLOCK_TYPE_ID' => 'lists'], 'select' => ['ID', 'CODE', 'NAME']])->fetchAll();print_r($rows); // список живёт инфоблоком особого типа// на разных стендах совпадает код, а не числовой идентификаторКод инфоблока - единственная надёжная опора при переносе. Именно по нему миграция понимает, создавать список заново или дополнять уже существующий.
Создаём список миграцией:
$iblock = new \CIBlock();$id = $iblock->Add(['IBLOCK_TYPE_ID' => 'lists', 'CODE' => 'vendor_registry', 'NAME' => 'Реестр заявок', 'SITE_ID' => ['s1'], 'ACTIVE' => 'Y']);if (!$id) { throw new \Exception($iblock->LAST_ERROR); } // ошибку не глотаемДобавляем поля с постоянными кодами:
(new \CIBlockProperty())->Add(['IBLOCK_ID' => $id, 'CODE' => 'CONTRACT_NO', 'NAME' => 'Номер договора', 'PROPERTY_TYPE' => 'S', 'IS_REQUIRED' => 'Y']);(new \CIBlockProperty())->Add(['IBLOCK_ID' => $id, 'CODE' => 'DEADLINE', 'NAME' => 'Срок', 'PROPERTY_TYPE' => 'S', 'USER_TYPE' => 'Date']);// код поля попадает в шаблоны и отчёты, поэтому его придумывают один разБуквенные коды полей переживают любой перенос. Обращение по номеру свойства работает только на том стенде, где этот номер выдан, и это самая частая поломка после выкладки.
Повторяем права групп:
\CIBlock::SetPermission($id, [ '1' => 'X', // администраторы: полный доступ '7' => 'W', // группа менеджеров: правка записей '2' => 'D', // все посетители: доступа нет]);Права на список задают в той же миграции, что и структуру. Иначе на боевом сайте список появляется пустым для всех, кроме администратора, и это замечают уже сотрудники.
Заливаем записи по внешнему коду:
$el = new \CIBlockElement();foreach ($rows as $row) { $exists = \CIBlockElement::GetList([], ['IBLOCK_ID' => $id, 'XML_ID' => $row['code']], false, false, ['ID'])->Fetch(); $fields = ['IBLOCK_ID' => $id, 'NAME' => $row['name'], 'XML_ID' => $row['code'], 'PROPERTY_VALUES' => ['CONTRACT_NO' => $row['contract']]]; $exists ? $el->Update($exists['ID'], $fields) : $el->Add($fields);}Типичные проблемы
После переноса шаблон выводит пустые значения полей.
Код обращается к свойству по числовому идентификатору, а на боевом стенде он другой. Полям задают понятные буквенные коды и обращаются к значениям только по этим кодам.
Сотрудники не видят список на боевом сайте.
Права групп на список остались на стенде разработки и в миграцию не попали. Права выдают тем же кодом миграции, которым создаётся сама структура списка.
Повторный запуск миграции завёл второй такой же список.
Миграция создаёт список, не проверяя, нет ли уже инфоблока с этим кодом. Перед созданием проверяют существование инфоблока по коду и дополняют найденный.
Записи задвоились после повторной заливки данных.
Записи создаются заново, потому что сопоставления по внешнему коду источника в скрипте нет. Перед добавлением ищут запись с таким внешним кодом и обновляют найденную вместо создания.
Список перенесён выгрузкой базы и утянул чужие данные.
Выгрузка таблиц базы переносит на боевой сайт идентификаторы и записи стенда разработки целиком. Структуру списка переносят миграцией, а данные - отдельным управляемым шагом.
Частые вопросы
Чем универсальный список отличается от инфоблока?
Технически это инфоблок особого типа с готовым интерфейсом правки для сотрудников. Поэтому и переносится он инфоблочными средствами, а не отдельным механизмом.
Можно ли перенести список выгрузкой базы?
Можно, но вместе с ним приедут идентификаторы и записи стенда разработки. На боевом сайте это оборачивается расхождением данных и правами из чужой среды.
Что делать с настройками вывода полей?
Их задают в интерфейсе списка после переноса структуры и фиксируют в описании миграции. Это самая забываемая часть: список приезжает, а колонки в нём другие.
Как переносить записи, если их тысячи?
Порциями по паре сотен, сопоставляя по внешнему коду и ведя журнал прохода. Разовый перенос всего файла упирается во время выполнения скрипта.
Нужен ли список, если есть highload-блок?
Список удобнее, когда поля меняет сам заказчик и нужны права на записи. Highload-блок берут ради объёма и скорости, а не ради интерфейса.
Смежное
-
Универсальный список не открывается или пуст: разбор причин - разбор списка, не заработавшего после переноса
-
Универсальные списки - оглавление подтемы
-
Универсальный список: настройка, права и вывод элементов - как список заводят руками
-
Список как справочник: поля, права, вывод и наполнение - когда список удобнее инфоблока
-
Миграции структуры: перенос инфоблоков и настроек между стендами - устройство самих миграций
-
Права на инфоблок и заказы: выдача из интерфейса и кодом - как раздают права на записи
-
Highload-блок на объёме: индексы, заливка, выкладка структуры - соседнее хранилище и его перенос
-
Контентные модули - устройство модулей контента целиком
-
Перенос бизнес-процесса между стендами: шаблон, привязка, права - перенос процессов над этим списком
-
Универсальный список изнутри: инфоблок, поля, права - что именно переносится вместе со списком