Налаштування масової прив'язки торгових пропозицій 1С-Бітрікс
Торгові пропозиції в Бітрікс — це елементи окремого інфоблоку, кожен із яких прив'язаний до батьківського товару через поле CML2_LINK (зберігається в b_iblock_element_property). Коли у вас тисячі SKU і ця прив'язка порушена — пропозиції не відображаються в картці товару, ціни та залишки не показуються. Завдання масової прив'язки виникає при міграції з іншої платформи, імпорті з 1С з помилками або ручному створенні бази.
Як працює зв'язок товар — торгова пропозиція
Інфоблок каталогу містить основні товари. Для торгових пропозицій створюється пов'язаний інфоблок — його ID вказується в полі OFFERS_IBLOCK_ID у b_iblock.ID. Зв'язок оголошується через b_iblock_fields або через інтерфейс: Інфоблоки → Типи інфоблоків → Торговий каталог → Редагувати.
Кожна торгова пропозиція має властивість із кодом CML2_LINK (тип «Прив'язка до елементів») — значення в b_iblock_element_property.VALUE відповідає ID батьківського товару.
-- Перевірити, у скількох пропозицій не заповнена прив'язка:
SELECT COUNT(*)
FROM b_iblock_element ie
WHERE ie.IBLOCK_ID = {offers_iblock_id}
AND NOT EXISTS (
SELECT 1 FROM b_iblock_element_property iep
INNER JOIN b_iblock_property ip ON ip.ID = iep.IBLOCK_PROPERTY_ID
WHERE iep.IBLOCK_ELEMENT_ID = ie.ID
AND ip.CODE = 'CML2_LINK'
AND iep.VALUE IS NOT NULL
);
Знаходження ID властивості CML2_LINK
$offersIblockId = 11; // ID інфоблоку торгових пропозицій
$propRes = \Bitrix\Iblock\PropertyTable::getList([
'filter' => ['IBLOCK_ID' => $offersIblockId, 'CODE' => 'CML2_LINK'],
'select' => ['ID'],
])->fetch();
$linkPropertyId = $propRes['ID'];
Масова прив'язка за XML_ID
Найпоширеніший сценарій: у товарів і пропозицій в b_iblock_element.XML_ID зберігається артикул із 1С. Прив'язка робиться за збігом артикулу або за маппінговою таблицею.
// Приклад: прив'язуємо пропозиції до товарів за першими 8 символами XML_ID
// Товар: XML_ID = 'PROD-001', Пропозиції: XML_ID = 'PROD-001-S', 'PROD-001-M', 'PROD-001-L'
$catalogIblockId = 10;
$offersIblockId = 11;
// Збираємо карту товарів: XML_ID → ID елемента
$productMap = [];
$productsRes = \CIBlockElement::GetList([], ['IBLOCK_ID' => $catalogIblockId], false, false, ['ID', 'XML_ID']);
while ($row = $productsRes->Fetch()) {
$productMap[$row['XML_ID']] = $row['ID'];
}
// Обробляємо пропозиції пакетами
$offersRes = \CIBlockElement::GetList([], ['IBLOCK_ID' => $offersIblockId], false, false, ['ID', 'XML_ID']);
$batch = [];
while ($row = $offersRes->Fetch()) {
// Визначаємо XML_ID батька: беремо перші N символів або парсимо за роздільником
$parentXmlId = substr($row['XML_ID'], 0, 8); // налаштуйте під свою схему
if (!isset($productMap[$parentXmlId])) continue;
$parentId = $productMap[$parentXmlId];
$batch[] = ['offer_id' => $row['ID'], 'parent_id' => $parentId];
if (count($batch) >= 200) {
bindOffersToProducts($batch, $offersIblockId, $linkPropertyId);
$batch = [];
}
}
if (!empty($batch)) {
bindOffersToProducts($batch, $offersIblockId, $linkPropertyId);
}
function bindOffersToProducts(array $batch, int $iblockId, int $propId): void
{
foreach ($batch as $item) {
// Перевіряємо, чи є вже запис
$existing = \Bitrix\Iblock\ElementPropertyTable::getList([
'filter' => [
'IBLOCK_ELEMENT_ID' => $item['offer_id'],
'IBLOCK_PROPERTY_ID' => $propId,
],
'select' => ['ID'],
])->fetch();
if ($existing) {
\Bitrix\Iblock\ElementPropertyTable::update($existing['ID'], [
'VALUE' => $item['parent_id'],
]);
} else {
\Bitrix\Iblock\ElementPropertyTable::add([
'IBLOCK_ELEMENT_ID' => $item['offer_id'],
'IBLOCK_PROPERTY_ID' => $propId,
'VALUE' => $item['parent_id'],
]);
}
}
}
Прив'язка через CSV-маппінг
Якщо логіка визначення батька складніша — використовуйте зовнішню карту:
offer_xml_id,parent_xml_id
SKU-001-RED,PROD-001
SKU-001-BLUE,PROD-001
SKU-002-S,PROD-002
$map = parseCsv('/import/offers_mapping.csv'); // [['offer_xml_id' => ..., 'parent_xml_id' => ...]]
foreach ($map as $row) {
$offerId = getElementIdByXmlId($offersIblockId, $row['offer_xml_id']);
$parentId = getElementIdByXmlId($catalogIblockId, $row['parent_xml_id']);
if ($offerId && $parentId) {
\CIBlockElement::SetPropertyValues($offerId, $offersIblockId, $parentId, 'CML2_LINK');
}
}
Перевірка результату та інвалідація кешу
Після масової прив'язки обов'язково:
- Перевірте кілька товарів у публічній частині — пропозиції повинні відображатися в картці
- Скиньте кеш інфоблоків для обох інфоблоків
- Переіндексуйте фасетний фільтр, якщо пропозиції беруть участь у фільтрації
\Bitrix\Iblock\InformationBlock::cleanTagCache($catalogIblockId);
\Bitrix\Iblock\InformationBlock::cleanTagCache($offersIblockId);
\Bitrix\Iblock\PropertyIndex\Manager::markIblockToReindex($offersIblockId);
Терміни виконання
| Обсяг | Час |
|---|---|
| До 1 000 пропозицій | 2–4 години (аналіз + скрипт + перевірка) |
| 1 000–20 000 пропозицій | 1 день |
| 20 000+ пропозицій | 2–3 дні (включно з відлагодженням маппінгу та верифікацією) |







