Перенос инфоблока выгрузкой в XML - структура, свойства, данные
Переносим инфоблок между стендами штатной выгрузкой в XML. На приёмник уезжает одна структура со свойствами и элементами, а вся остальная база остаётся нетронутой.
Решение
Что уезжает в файл
Смотрим состав инфоблока перед выгрузкой:
\Bitrix\Main\Loader::includeModule('iblock');$iblock = \Bitrix\Iblock\IblockTable::getRow([ 'filter' => ['=CODE' => 'catalog', '=IBLOCK_TYPE_ID' => 'catalog'], 'select' => ['ID', 'NAME', 'XML_ID'], // XML_ID - внешний код самого инфоблока]);$props = (new CIBlock)->GetProperties($iblock['ID'], [], []); // свойства уедут вместе с элементамиВ файл попадают сам инфоблок, его свойства, разделы, элементы и значения свойств. На стенде остаются права доступа на инфоблок, настройки модулей и цены торгового каталога. Связанные Highload-справочники в файл тоже не уедут, и на приёмнике их заводят отдельно.
Формат файла - обычный XML. Он читается глазами и правится текстовым редактором. Размер растёт быстро: тысяча элементов даёт файл на десятки мегабайт. Картинки уезжают вложениями и увеличивают его ещё сильнее.
Выгрузка из админки
Запускаем выгрузку из списка инфоблоков:
Контент > Инфоблоки > Типы инфоблоков > catalogменю нужного инфоблока > Экспорт в XMLформат CommerceML 2, файл складывается на диск стендаВыгрузка идёт шагами, и каждый шаг обязан уложиться во время ответа скрипта. На инфоблоке в десятки тысяч элементов время шага ставят ниже лимита самого интерпретатора. Обычно это шестьдесят секунд, и превышение обрывает выгрузку на середине файла.
Проверяем лимиты перед выгрузкой большого каталога:
max_execution_time = 60 ; в этот предел обязан уложиться один шагmemory_limit = 256M ; разбор дерева XML держит узлы в памятиКартинки элементов лежат не внутри XML, а рядом с ним отдельной папкой. На приёмник её кладут целиком и с прежними именами папок и файлов. При переименовании папки загрузка не найдёт ни одного изображения из этого файла.
Загрузка на другом стенде
Проверяем номер инфоблока после загрузки:
$fresh = \Bitrix\Iblock\IblockTable::getRow([ 'filter' => ['=CODE' => 'catalog', '=IBLOCK_TYPE_ID' => 'catalog'], 'select' => ['ID'],]);echo $fresh['ID']; // номер выдаёт база приёмника, из файла он не приезжаетНомера инфоблока, его свойств и элементов на приёмнике окажутся совершенно другими. Прежний номер помнят параметры компонентов, свойства привязки и код самого проекта. Их перенастраивают руками либо сразу пишут через символьный код инфоблока и тип.
Сопоставление по внешнему коду
Ищем элемент по внешнему коду, а не по номеру:
$rs = CIBlockElement::GetList([], ['IBLOCK_ID' => $fresh['ID'], '=XML_ID' => '1000123'], false, false, ['ID', 'NAME', 'XML_ID']);// уникальность элемента при импорте - по внешнему коду, при его отсутствии - по названиюВнешний код и есть тот ключ, по которому повторная загрузка узнаёт прежние
записи. Элементы с пустым XML_ID импорт при повторном запуске опознать не
может. Вторая загрузка того же файла заводит рядом вторые копии всех элементов.
Перенос из кода при установке решения
Грузим инфоблок из кода готового решения:
$iblockId = WizardServices::ImportIBlockFromXML( $xmlFile, // файл лежит в /xml/<ID языка>/ решения $iblockCode, $iblockType, $siteID);CWizardUtil::ReplaceMacros(WIZARD_SITE_PATH . '/catalog/index.php', ['CATALOG_IBLOCK_ID' => $iblockId]); // новый номер подставляем в файлыВ исходниках решения вместо номера стоит переносимый макрос #CATALOG_IBLOCK_ID#.
Реальное значение подставляет мастер установки, получив номер только что
созданного инфоблока. Тип инфоблока заводят до импорта, иначе элементы лягут в
первый подходящий чужой.
Проверка после переноса
Сбрасываем кэш и помечаем индекс устаревшим:
CIBlock::clearIblockTagCache($fresh['ID']);\Bitrix\Iblock\PropertyIndex\Manager::markAsInvalid($fresh['ID']);// фасетный индекс после загрузки с новыми свойствами сам не пересобираетсяДальше проверяют глазами всё то, что штатный файл выгрузки перенести не мог. Права групп, привязку к сайтам и настройки умного фильтра задают на приёмнике руками. SEO-шаблоны инфоблока переносят миграцией либо повторяют по образцу с исходного стенда.
Типичные проблемы
После импорта в инфоблоке нет цен.
Цены живут в модуле торгового каталога, а не в самом инфоблоке сайта. В выгрузку структуры они не попадают, поэтому их переносят импортом каталога.
Загрузка создала второй инфоблок с тем же названием.
Внешний код инфоблока на приёмнике не совпал с кодом из принятого файла. Совпадение названий системе ничего не говорит, сопоставление идёт только по коду.
Повторная загрузка файла завела копии элементов.
У элементов пустой XML_ID, и опознать прежние записи импорту попросту нечем. Тогда он заводит новые элементы вместо обновления тех, что уже есть.
Картинки видно в админке, а на витрине нет.
Кэш компонентов остался с выборкой, собранной ещё до загрузки нового файла. Его сбрасывают тем же шагом переноса, каким выполняют и сам импорт.
Импорт обрывается на большом файле.
Шаг загрузки упирается в максимальное время исполнения скрипта на приёмнике. Время шага ставят заведомо ниже лимита интерпретатора, обычно около шестидесяти секунд.
Частые вопросы
Как перенести инфоблок с тестового сайта на боевой?
Выгрузить его в XML на стенде и загрузить полученный файл на боевом сайте. Так уезжает одна структура с элементами, а заказы и правки контент-менеджеров на боевом остаются нетронутыми.
Переносятся ли цены при импорте инфоблока из XML?
Нет. Цены хранит модуль торгового каталога, а не инфоблок, поэтому после загрузки в свойствах элементов их не окажется. Цены переносят отдельным шагом, средствами импорта каталога.
Почему после переноса у инфоблока другой номер?
Номер выдаёт база приёмника, из файла он не приезжает. Поэтому в коде и в параметрах компонентов инфоблок ищут по символьному коду и типу, а номер получают уже из выборки.
Куда загружать папку с картинками при импорте из XML?
На приёмник, целиком и с прежними именами папок и файлов. Пути к изображениям записаны внутри XML, и при переименовании папки загрузка не найдёт ни одного файла.
Можно ли загрузить инфоблок из XML программно?
Да, методом WizardServices::ImportIBlockFromXML из мастера установки решения. Он возвращает номер созданного инфоблока, а дальше номер подставляют в файлы через CWizardUtil::ReplaceMacros.
Смежное
- Git и выкладка - оглавление подтемы
- Архитектура проекта - что где лежит в проекте на платформе
- Миграции структуры: перенос инфоблоков и настроек между стендами - тот же перенос, но кодом и с журналом применённых
- Три контура проекта: разработка, тест, бой и порядок переноса - между какими стендами ходит файл выгрузки
- Выкладка на боевой: порядок, структура, откат - куда встроить загрузку файла на боевом
- Импорт каталога из файла: CSV, повторный запуск, свои поля - табличный формат вместо XML
- Импорт каталога изнутри: файлы, сопоставление, перезапись - как разбирает файлы обмен с 1С
- Дубли товаров после обмена: поиск и разведение - что делать с копиями от пустого внешнего кода
- Свойства инфоблока: чтение, запись и фильтрация по значению - что именно уезжает в файл вместе с элементами
- Перенос универсального списка между стендами: структура, права, данные - тот же вопрос для списков
- Стенд из копии боевого: подъём, обезличивание, отрезанные связи - обратное направление переноса данных