Структура каталога при выгрузке из 1С - разделы, вложенность, две базы
Разбираемся, как группы номенклатуры 1С становятся разделами инфоблока и что делать, когда дерево приезжает не таким, как нужно сайту.
Решение
Смотрим, что приехало в разделы после обмена:
$sections = CIBlockSection::GetList( ['LEFT_MARGIN' => 'ASC'], // порядок обхода дерева ['IBLOCK_ID' => $iblockId], false, ['ID', 'NAME', 'DEPTH_LEVEL', 'XML_ID']);while ($s = $sections->Fetch()) { printf("%s%-30s xml_id=%s\n", str_repeat(' ', $s['DEPTH_LEVEL'] - 1), $s['NAME'], $s['XML_ID']);}Вложенность приезжает из 1С как есть: сколько уровней в справочнике номенклатуры, столько и в инфоблоке. Сайт её не выпрямляет и не схлопывает, даже если витрине удобнее два уровня вместо пяти.
Поле XML_ID у раздела - тот же внешний код, что и у товара. По нему обмен
находит раздел при повторной выгрузке и решает, обновить его или создать новый
рядом. Пустой внешний код у раздела означает, что его завели на сайте руками, и
обмен такой раздел не тронет.
Раскладываем товары сами, если дерево не выгружается:
AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', 'routeBySupplier');
function routeBySupplier(&$arFields){ if (($_REQUEST['mode'] ?? '') !== 'import') { return; } $code = $arFields['PROPERTY_VALUES'][SUPPLIER_PROP_ID][0]['VALUE'] ?? null; if ($code && isset(SECTION_BY_SUPPLIER[$code])) { $arFields['IBLOCK_SECTION'] = [SECTION_BY_SUPPLIER[$code]]; }}Такой обработчик нужен, когда в 1С плоский список, а на сайте нужна витрина по разделам. Раскладка идёт по свойству товара, а не по группе номенклатуры.
Разводим две базы 1С по корневым разделам:
// каждой базе свой корень: внешние коды групп в разных базах совпадают$section = new CIBlockSection();$rootA = $section->Add(['IBLOCK_ID' => $iblockId, 'NAME' => 'Основной склад', 'XML_ID' => 'base-a']);$rootB = $section->Add(['IBLOCK_ID' => $iblockId, 'NAME' => 'Филиал', 'XML_ID' => 'base-b']);Без разведения вторая база перезапишет разделы первой: обмен сопоставляет группы по внешнему коду, а нумерация в двух базах 1С идёт независимо.
Удерживаем товар в разделе, назначенном на сайте:
function keepSiteSection(&$arFields){ if (($_REQUEST['mode'] ?? '') === 'import') { unset($arFields['IBLOCK_SECTION'], $arFields['IBLOCK_SECTION_ID']); }}Иначе каждый обмен возвращает товар в группу из 1С, и ручная раскладка живёт до следующей выгрузки.
Выбор между двумя подходами стоит сделать один раз и записать в проекте. Либо дерево ведёт 1С, и тогда сайт не трогает разделы вовсе, либо раскладку ведёт сайт, и тогда привязка снимается на каждом обмене. Смешанный вариант, когда часть разделов ведёт 1С, а часть контент-менеджер, разъезжается через месяц: никто уже не помнит, какой раздел чей, и правки затираются молча.
Типичные проблемы
Товары приехали в корень инфоблока, разделов нет.
Группы номенклатуры не попали в выгрузку. Обмен разбирает группы отдельным узлом до товаров, и если 1С их не прислала, привязывать товар не к чему.
После второго обмена дерево разделов задвоилось.
Внешние коды групп изменились: так бывает после переноса базы 1С. Сайт не нашёл прежних разделов и создал новые рядом со старыми.
Товар переехал в другой раздел сам.
В 1С его перенесли в другую группу, и обмен повторил перенос. Привязку снимают обработчиком, если раскладку на сайте ведёт контент-менеджер.
Разделы из двух баз 1С затирают друг друга.
Нумерация групп в базах независима, и внешние коды совпадают. Каждой базе выделяют свой корневой раздел и выгружают внутрь него.
Частые вопросы
Можно ли выгрузить товары без дерева каталога?
Да, если в 1С не выгружать группы. Товары приедут в корень инфоблока, а раскладку по разделам делают на сайте своим обработчиком по свойству товара - поставщику, бренду, назначению.
Как сохранить структуру 1С, но переименовать разделы на сайте?
Названия обмен перезаписывает вместе с остальными полями раздела. Свои названия удерживают тем же приёмом, что и у товаров: снимают поле NAME в обработчике OnBeforeIBlockSectionUpdate по признаку mode=import.
Что будет с товарами, если группу в 1С удалить?
Раздел на сайте останется, а товары из него 1С перенесёт в другую группу при следующем обмене. Пустые разделы обмен не убирает: их чистят отдельно, сверяясь с присланным деревом.
Обязательно ли совпадение вложенности сайта и 1С?
Нет, но всё, что приходит из 1С, воспроизводится один в один. Другая структура на сайте держится только обработчиком, и её надо восстанавливать при каждом обмене.
Смежное
- Обмен: выгрузка товаров и номенклатуры - оглавление подтемы
- Выгрузка товаров из 1С на сайт - настройка и запуск обмена
- Обмен с 1С и HTTP - устройство обмена целиком
- Инфоблоки - разделы и их вложенность
- Каталог с сайта в 1С: обратное направление выгрузки - внешние коды как основа сопоставления
- Дубли товаров после обмена: поиск и разведение - когда разделы приезжают повторно
- Правка структуры разделов: перенос, слияние, удаление - правка дерева на стороне сайта