CIBlockSection::GetByID и построение цепочки родительских
разделов — базовая задача при выводе хлебных крошек, вложенных
каталогов и любой структуры, где разделы образуют иерархию.
Разберём метод и типичные способы получить полную цепочку от текущего
раздела до корня.
Получение одного раздела по ID
<?php
$section = CIBlockSection::GetByID($sectionId)->GetNext();
if ($section) {
echo $section['NAME'];
echo $section['IBLOCK_SECTION_ID']; // ID родительского раздела, если есть
}
Как и большинство старых методов API инфоблоков, GetByID
возвращает не готовый массив, а объект-курсор — значение нужно
забрать вызовом GetNext(). Если раздел с указанным ID
не найден или деактивирован, GetNext() вернёт
false.
Построение цепочки разделов до корня
Поле IBLOCK_SECTION_ID хранит ID родительского раздела —
чтобы построить полную цепочку (например, для хлебных крошек),
нужно подниматься по ней вручную:
<?php
function getSectionChain(int $sectionId): array
{
$chain = [];
$currentId = $sectionId;
while ($currentId) {
$section = CIBlockSection::GetByID($currentId)->GetNext();
if (!$section) {
break;
}
array_unshift($chain, $section);
$currentId = (int)$section['IBLOCK_SECTION_ID'];
}
return $chain;
}
$chain = getSectionChain($sectionId);
foreach ($chain as $section) {
echo $section['NAME'] . ' / ';
}
Такой цикл делает по одному запросу на каждый уровень вложенности — для структуры из трёх-четырёх уровней это не проблема, но на глубокой иерархии или при частом использовании на каждой странице стоит подумать о кешировании результата.
Нужна помощь с Битрикс?
Готовый способ: GetNavChain
<?php
$navChain = CIBlockSection::GetNavChain($iblockId, $sectionId);
while ($section = $navChain->GetNext()) {
echo $section['NAME'] . ' > ';
}
GetNavChain делает то же самое — строит цепочку
от корня до указанного раздела — но одним вызовом, без ручного
цикла. В большинстве случаев он удобнее самописного варианта
и достаточен для типовых хлебных крошек.
Кеширование цепочки на страницах каталога
<?php
use Bitrix\Main\Data\Cache;
$cache = Cache::createInstance();
$cacheId = 'section_chain_' . $sectionId;
if ($cache->initCache(86400, $cacheId, '/section_chain/')) {
$chain = $cache->getVars();
} elseif ($cache->startDataCache()) {
$chain = getSectionChain($sectionId);
$cache->endDataCache($chain);
}
Структура разделов каталога меняется редко, поэтому цепочку для хлебных крошек можно кешировать на сутки — это снимает несколько дополнительных запросов на каждой странице раздела без риска показать устаревшие данные надолго.
Получение полного списка дочерних разделов
<?php
$childSections = [];
$result = CIBlockSection::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => $iblockId, 'SECTION_ID' => $sectionId, 'ACTIVE' => 'Y']
);
while ($section = $result->GetNext()) {
$childSections[] = $section;
}
Обратная задача — получить не родителей, а прямых потомков раздела —
решается через GetList с фильтром по
SECTION_ID, а не через GetByID, который
всегда возвращает только один конкретный раздел.
Частые ошибки
- Забыли вызвать GetNext() после GetByID. Переменная содержит объект-курсор вместо массива данных раздела.
- Ручной цикл построения цепочки без кеша. На страницах с глубокой вложенностью — лишние запросы на каждый визит.
- Путаница между SECTION_ID и IBLOCK_SECTION_ID в фильтре. Один используется для поиска потомков, другой хранится в самом разделе как ссылка на родителя.
Итог
Для получения одного раздела по ID используется
CIBlockSection::GetByID, для построения полной цепочки
от корня до раздела — готовый GetNavChain, который
избавляет от необходимости писать ручной рекурсивный обход. Для
часто запрашиваемых цепочек на страницах каталога стоит добавить
кеширование, поскольку структура разделов меняется значительно реже,
чем запрашивается.
