Разделы инфоблока образуют дерево, по которому строится структура каталога, рубрики новостей или любая другая иерархия контента. Разберём, как их настраивать и выводить дерево программно — задача, которая на практике решается несколькими разными способами в зависимости от того, нужна ли полная гибкость или достаточно готового компонента.
Настройка через административную часть
Разделы создаются в разделе Контент → выбранный инфоблок → Разделы. Каждый раздел имеет название, символьный код, сортировку, привязку к родительскому разделу и, при необходимости, собственные UF-поля — например, изображение раздела или текстовое описание для страницы категории каталога.
Ограничение глубины
Формально Битрикс не ограничивает вложенность разделов, но практический предел — три-четыре уровня. Более глубокая структура усложняет навигацию для посетителя и требует более сложной логики построения меню и хлебных крошек. Если кажется, что нужно больше уровней, часто это признак того, что структуру стоит пересмотреть, а не добавлять ещё один уровень вложенности.
Нужна помощь с Битрикс?
Вывод дерева разделов компонентом
Для типовых случаев есть готовые компоненты, не требующие написания кода:
<$APPLICATION->IncludeComponent(
'bitrix:catalog.section.list',
'main',
[
'IBLOCK_TYPE' => 'catalog',
'IBLOCK_ID' => 5,
'SECTION_ID' => 0,
'COUNT_ELEMENTS' => 'Y',
'TOP_DEPTH' => 2,
'ADD_SECTIONS_CHAIN' => 'N',
'VIEW_MODE' => 'LINE',
]
);?>
Получение дерева из кода
Когда готового компонента недостаточно, дерево строится напрямую через API:
<?php
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
function getSectionTree(int $iblockId, int $parentId = 0): array
{
$tree = [];
$result = CIBlockSection::GetList(
['SORT' => 'ASC'],
[
'IBLOCK_ID' => $iblockId,
'ACTIVE' => 'Y',
'SECTION_ID' => $parentId,
],
false,
['ID', 'NAME', 'CODE']
);
while ($section = $result->GetNext()) {
$section['CHILDREN'] = getSectionTree($iblockId, $section['ID']);
$tree[] = $section;
}
return $tree;
}
$tree = getSectionTree(5);
Рекурсивная функция вызывает саму себя для каждого найденного раздела, собирая дочерние разделы вложенным массивом. На большом дереве с сотнями разделов такой подход создаёт много отдельных запросов — по одному на каждый уровень вложенности каждой ветки.
Оптимизация: одна выборка вместо рекурсии
Для больших деревьев эффективнее получить все разделы одним запросом и собрать иерархию уже в памяти PHP:
<?php
$result = CIBlockSection::GetList(
['LEFT_MARGIN' => 'ASC'],
['IBLOCK_ID' => 5, 'ACTIVE' => 'Y'],
false,
['ID', 'NAME', 'IBLOCK_SECTION_ID']
);
$flat = [];
while ($section = $result->GetNext()) {
$flat[$section['ID']] = $section;
$flat[$section['ID']]['CHILDREN'] = [];
}
$tree = [];
foreach ($flat as $id => &$section) {
$parentId = $section['IBLOCK_SECTION_ID'];
if ($parentId && isset($flat[$parentId])) {
$flat[$parentId]['CHILDREN'][] = &$section;
} else {
$tree[] = &$section;
}
}
unset($section);
Здесь один запрос к базе вместо десятков или сотен, а сборка иерархии происходит в оперативной памяти — заметно быстрее на дереве с реальным объёмом разделов, особенно в сочетании с кешированием результата.
Сортировка LEFT_MARGIN / RIGHT_MARGIN
Поля LEFT_MARGIN и RIGHT_MARGIN — служебная
реализация дерева по методу вложенных множеств. Сортировка по
LEFT_MARGIN возвращает разделы уже в правильном
порядке обхода дерева, что удобно использовать вместо построения
иерархии вручную, если достаточно линейного списка с отступами
по уровню вложенности.
Кеширование дерева
Дерево разделов меняется редко по сравнению с элементами внутри
него, поэтому результат построения дерева — хороший кандидат
для кеширования через Bitrix\Main\Data\Cache,
с тегом на инфоблок, чтобы кеш сбрасывался автоматически при
добавлении или изменении раздела.
Частые ошибки
- Рекурсивный обход без кеширования на большом дереве. Каждый показ страницы пересчитывает структуру заново.
- Слишком глубокая вложенность. Пять и более уровней усложняют и код, и навигацию для посетителя.
- Не выбираются нужные поля явно. Выборка всех полей раздела вместо конкретно нужных увеличивает объём данных.
- Игнорируется готовый компонент там, где типового вывода дерева было бы достаточно — своя реализация пишется без необходимости.
Итог
Разделы инфоблока настраиваются в административной части и образуют дерево, глубину которого разумно ограничивать тремя-четырьмя уровнями. Для типового вывода хватает готового компонента, а для собственной логики построение дерева одним запросом с последующей сборкой иерархии в памяти работает заметно быстрее рекурсивного обхода с запросом на каждый уровень.
