Выгрузка свойств товара из 1С - типы, коды и множественные значения
Разбираемся, как реквизиты номенклатуры 1С превращаются в свойства инфоблока и почему они приезжают не теми, какими ожидались.
Решение
Смотрим внешние коды свойств инфоблока:
$props = CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId]);while ($prop = $props->Fetch()) { printf("%-24s %-12s xml_id=%s\n", $prop['CODE'], $prop['PROPERTY_TYPE'], $prop['XML_ID']);}Обмен сопоставляет свойства не по названию и не по коду, а по XML_ID. Именно в
нём лежит идентификатор реквизита из 1С, и именно он разъезжается после переноса
базы.
Создаём свойство нужного типа до первого обмена:
$property = new CIBlockProperty();$property->Add([ 'IBLOCK_ID' => $iblockId, 'NAME' => 'Цвет', 'CODE' => 'COLOR', 'PROPERTY_TYPE' => 'L', // список; после обмена тип уже не сменить 'MULTIPLE' => 'N', 'XML_ID' => $guidFrom1C,]);Тип свойства обмен не меняет. Если свойство создалось автоматически при первой выгрузке, оно почти всегда получится строкой, и перевести его в список или в привязку к элементам потом можно только пересозданием.
Включаем множественность там, где значений несколько:
CIBlockProperty::Update($propertyId, ['MULTIPLE' => 'Y']);У одиночного свойства обмен запишет последнее пришедшее значение и молча отбросит остальные. Ошибки в логе при этом не будет: с точки зрения обмена он всё сохранил.
Проверяем, что приехало, на конкретном товаре:
$el = CIBlockElement::GetList([], ['IBLOCK_ID' => $iblockId, 'XML_ID' => $xmlId], false, false, ['ID']);$row = $el->Fetch();$values = CIBlockElement::GetProperty($iblockId, $row['ID'], [], []);while ($v = $values->Fetch()) { echo "{$v['CODE']}: {$v['VALUE']}\n";}Такая выборка показывает и пустые свойства, поэтому по ней видно не только что приехало, но и что осталось незаполненным.
Привязываем существующее свойство к реквизиту 1С:
// XML_ID берём из выгруженного файла: <Свойство><Ид>...</Ид></Свойство>CIBlockProperty::Update($propertyId, ['XML_ID' => 'e4f1c0a2-9b3d-11ee-8c90-0242ac120002']);
// после правки сбрасываем кеш свойств инфоблока, иначе обмен возьмёт старую картуCIBlock::CleanCache($iblockId);Так свойство перестаёт дублироваться: обмен находит его по коду и пишет в него, вместо того чтобы заводить новое рядом.
Сравнивать удобно с самим XML: обмен складывает присланные файлы в
/upload/1c_catalog/, и там видно, что 1С действительно отправила. Если в XML
реквизита нет, дело не в сайте, а в отборе на стороне 1С.
Отдельная история - свойства торговых предложений. Они живут в своём инфоблоке,
и коды у них свои: одноимённое свойство товара и предложения это два разных
свойства с разными XML_ID. Путаница между ними даёт классическую картину,
когда у товара характеристика пустая, а у его предложений заполнена.
Смотрим, что 1С прислала по конкретному реквизиту:
# в файле import.xml узел свойства лежит рядом с его значением у товараgrep -A3 -m5 '<Свойство>' /home/bitrix/www/upload/1c_catalog/import*.xmlgrep -c '<ЗначенияСвойства>' /home/bitrix/www/upload/1c_catalog/import*.xmlПорядок разбора внутри файла тоже важен. Справочники приезжают до товаров, и свойство типа «привязка к элементам» находит цель только если она уже в базе. При первом обмене на пустом каталоге такие свойства часто остаются пустыми и заполняются лишь со второго прогона.
Типичные проблемы
Свойство приехало строкой вместо списка.
Свойство создал сам обмен при первой выгрузке. Тип он выбирает строковый и потом не меняет: нужное свойство заводят руками до первого обмена и проставляют ему XML_ID реквизита.
Из нескольких значений сохранилось одно.
У свойства снят флаг множественности. Обмен пишет значения по очереди, каждое следующее затирает предыдущее, и в базе остаётся последнее.
В инфоблоке появились свойства, которых не заводили.
В 1С у реквизита стоит признак выгрузки на сайт. Убирать их надо в 1С: удалённое на сайте свойство вернётся при следующем обмене.
Свойство типа «привязка к элементам» приезжает пустым.
Обмен передаёт значение внешним кодом, и элемент-цель должен быть выгружен раньше. Если справочник приезжает в том же файле после товаров, привязка не находит цели.
Частые вопросы
Можно ли сопоставить реквизит 1С с уже существующим свойством сайта?
Да, для этого свойству проставляют XML_ID, равный идентификатору реквизита в 1С. После этого обмен пишет в него, а не создаёт новое. Идентификатор смотрят в выгруженном XML, в узле свойства.
Почему картинки из свойства приезжают одной штукой?
Свойство типа «файл» тоже подчиняется флагу множественности. Для нескольких картинок его включают до обмена, иначе в базе останется последний присланный файл.
Как выгрузить только часть реквизитов?
Отбор задаётся на стороне 1С признаком выгрузки у реквизита. Со стороны сайта отфильтровать входящие свойства нечем: обмен разбирает файл целиком.
Что будет со свойством, если его удалить на сайте?
При следующем обмене оно создастся заново, потому что 1С продолжает его присылать. Значения при этом потеряются: новое свойство получит новый внутренний идентификатор.
Смежное
-
Обмен: выгрузка товаров и номенклатуры - оглавление подтемы
-
Выгрузка товаров из 1С на сайт - настройка и запуск обмена
-
Обмен с 1С и HTTP - устройство обмена целиком
-
Инфоблоки - как устроены свойства и их типы
-
Характеристики товара: группы свойств, порядок и пустые значения - что из приехавшего показывать покупателю
-
Импорт каталога изнутри: файлы, сопоставление, перезапись - как обмен создаёт свойства сам