На практике cron снял товар с раздела «Новинки», а утром карточка пропала из основного каталога и сменила URL — типичная ошибка merge. В админке привязка на месте, GetList показывает раздел, но catalog.section пустой: проблема не в ACTIVE, а в том, что в Update ушёл только новый IBLOCK_SECTION_ID без merge старых разделов, либо legacy SetElementSection не обновил фасетный индекс. Ниже — как читать привязки через GetElementGroups, безопасно обновлять через Update и вернуть товар на витрину.
Привязка элемента инфоблока к разделам в 1С-Битрикс: Управление сайтом хранится в b_iblock_section_element; IBLOCK_SECTION_ID задает основной раздел (влияет на URL), IBLOCK_SECTION - массив всех разделов при Add/Update. Текущие связи читают CIBlockElement::GetElementGroups; менять рекомендуется через Update, а не SetElementSection. После служебного SetElementSection при фасетном поиске нужен PropertyIndex\Manager::updateElementIndex. Сегодня: снимите разделы через GetElementGroups, сделайте merge, передайте оба ключа в Update и проверьте витрину.
Речь про 1С-Битрикс: Управление сайтом, не про Bitrix24. Смежные гайды: Add, Update, CIBlockSection, catalog.section.
Что такое привязка элемента к разделам инфоблока
Привязка элемента к разделу инфоблока битрикс iblock_section - связь товара или новости с одним или несколькими разделами. Данные лежат в b_iblock_section_element. В коде - два ключа: IBLOCK_SECTION_ID (основной раздел) и IBLOCK_SECTION (массив всех разделов).
Нужна при импорте и cron. Не нужна для разовой правки в админке. CIBlockSection::Update меняет раздел, не привязку элемента.
Разберите разницу IBLOCK_SECTION и IBLOCK_SECTION_ID
| Поле | Тип | URL | Ошибка |
|---|---|---|---|
| IBLOCK_SECTION_ID | один ID | Меняется при смене основного | Только новый ID - старые разделы сбросились |
| IBLOCK_SECTION | массив ID | Стабилен, если ID основного тот же | Один раздел в массиве - потеряли остальные |
Делайте: для элемента в нескольких разделах битрикс передавайте полный IBLOCK_SECTION. Не делайте: менять IBLOCK_SECTION_ID, если URL должен остаться.
Прочитайте привязки через CIBlockElement::GetElementGroups
В реальном проекте перед Update снимите список разделов. CIBlockElement::GetElementGroups($elementId, true) возвращает привязки элемента; true исключает связи через свойство «привязка к разделу».
$sectionIds = [];
$rs = CIBlockElement::GetElementGroups($elementId, true);
while ($row = $rs->Fetch()) {
$sectionIds[] = (int)$row['ID'];
}
- GetElementGroups($id, true) - массив ID в Fetch.
- Запомните IBLOCK_SECTION_ID из GetList, если URL нельзя менять.
- GetList показывает один раздел, GetElementGroups - три: доверяйте GetElementGroups.
Делайте: логируйте $sectionIds до/после. Не делайте: merge без чтения текущих привязок.
Обновите разделы через CIBlockElement::Update с merge
Канон iblock_section_id битрикс update - CIBlockElement::Update. Примечание 3: для новых разделов без смены главного передайте старый IBLOCK_SECTION_ID и полный IBLOCK_SECTION.
Workflow: GetElementGroups → merge add/del → Update → проверка витрины.
$el = new CIBlockElement;
$ok = $el->Update($elementId, [
'IBLOCK_SECTION_ID' => $mainSectionId,
'IBLOCK_SECTION' => array_values(array_diff($sectionIds, [99])),
]);
if (!$ok) { /* $el->LAST_ERROR */ }
- Add: array_unique(array_merge($sectionIds, [$newId])).
- Del: array_diff от GetElementGroups.
- IBLOCK_SECTION_ID: задайте явно, даже если не меняется; при false читайте $el->LAST_ERROR.
- События: Update вызывает OnBefore/OnAfterIBlockElementUpdate.
Делайте: тест на одном ID. Не делайте: IBLOCK_SECTION только с одним новым разделом.
Сравните SetElementSection и Update
CIBlockElement::SetElementSection - служебный legacy: не вызывает события Update и с 15.0.1 не обновляет фасетный индекс. Decision tree: новый код → Update; legacy → SetElementSection + updateElementIndex.
CIBlockElement::SetElementSection($elementId, $sectionIds);
\Bitrix\Iblock\PropertyIndex\Manager::updateElementIndex($iblockId, $elementId);
Если URL сменился, проверьте "Разрешить выбор основного раздела". Делайте: мигрируйте на Update. Не делайте: SetElementSection без updateElementIndex.
Проверьте видимость в catalog.section и умном фильтре
- ACTIVE элемента и родительских разделов.
- GetElementGroups совпадает с ожиданием; IBLOCK_SECTION_ID в массиве IBLOCK_SECTION.
- Фасетный индекс после SetElementSection - updateElementIndex.
- catalog.section: фильтр SECTION_ID и INCLUDE_SUBSECTIONS.
- Кеш компонента после cron.
Схема: GetElementGroups → Update → updateElementIndex → кеш → витрина. Делайте: сверяйте catalog.section. Не делайте: доверять только админке.
Что получите после чек-листа
Элемент останется в нужных разделах, URL стабилен, catalog.section синхронизирован с базой.
- GetElementGroups до/после на тестовом ID.
- Update с IBLOCK_SECTION_ID + полным IBLOCK_SECTION.
- Legacy - updateElementIndex или замена на Update.
- Сложный обмен - обсудите аудит.
Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: Update, GetElementGroups, SetElementSection, updateElementIndex.
Частые вопросы
Как привязать элемент к нескольким разделам в Битрикс?
Передайте массив IBLOCK_SECTION и IBLOCK_SECTION_ID для основного. Перед Update снимите список через GetElementGroups и сделайте merge - иначе лишние разделы пропадут.
Чем IBLOCK_SECTION отличается от IBLOCK_SECTION_ID?
IBLOCK_SECTION_ID - основной раздел и URL. IBLOCK_SECTION - все разделы витрины. Для "Акций" без смены URL зафиксируйте старый IBLOCK_SECTION_ID и расширьте IBLOCK_SECTION.
Как узнать все разделы элемента?
CIBlockElement::GetElementGroups($elementId, true) и цикл Fetch. IBLOCK_SECTION_ID в GetList - только основной, не полный набор.
Зачем нужен SetElementSection, если есть Update?
SetElementSection - legacy без событий Update и без фасетного индекса с 15.0.1. Новый код - Update; если legacy остался - PropertyIndex\Manager::updateElementIndex после вызова.
Почему товар не виден в разделе на сайте?
Проверьте ACTIVE, IBLOCK_SECTION, updateElementIndex после SetElementSection, SECTION_ID в catalog.section и кеш. Частый кейс: привязка в админке есть, индекс не пересчитан.
Как снять элемент с одного раздела, оставив в других?
GetElementGroups → array_diff → Update с прежним IBLOCK_SECTION_ID и обновленным IBLOCK_SECTION. Без merge со старыми ID разделы потеряются.
ciblockelement getelementgroups - что возвращает метод?
CIBlockElement::GetElementGroups возвращает разделы элемента. bElementOnly=true отсекает привязки через свойство. Читайте Fetch - это база для merge перед Update.
Было полезно?
Поставьте лайк, если статья помогла разобраться.
Поделиться статьёй
Отправьте тому, кому это пригодится.
Можно поделиться и фрагментом: выделите текст статьи.