7sites - внедрение Битрикс24
Услуги
  • Лицензии 1С-Битрикс
    • Облачный сервис Битрикс24
    • Коробочная версия Битрикс24
    • Подписка Битрикс24.Маркет Плюс
  • Внедрение CRM
  • Доработка корпоративных порталов Битрикс24
  • Техническое сопровождение
  • Перенос Битрикс24 из облака в коробку
  • Сайты на 1С-Битрикс24
Проекты
  • Государственные организации
  • Управление бизнесом
  • Спорт
  • Автомобильный бизнес
Акции
Новости
Компания
  • О компании
  • Сертификаты
  • Карьера
  • Разработка ПО
Контакты
Ещё
    Задать вопрос
    +7 (495) 118-30-89
    Заказать звонок
    info@7sites.ru
    г. Пермь, ш. Космонавтов 111, к. 10
    • Вконтакте
    • Facebook
    • Twitter
    • Telegram
    +7 (495) 118-30-89
    Заказать звонок
    7sites - внедрение Битрикс24
    Услуги
    • Лицензии 1С-Битрикс
      • Облачный сервис Битрикс24 —
      • Коробочная версия Битрикс24 —
      • Подписка Битрикс24.Маркет Плюс
    • Внедрение CRM
    • Доработка корпоративных порталов Битрикс24
    • Техническое сопровождение
    • Перенос Битрикс24 из облака в коробку
    • Сайты на 1С-Битрикс24
    Проекты
    • Государственные организации
    • Управление бизнесом
    • Спорт
    • Автомобильный бизнес
    Акции
    Новости
    Компания
    • О компании
    • Сертификаты
    • Карьера
    • Разработка ПО
    Контакты
      7sites - внедрение Битрикс24
      Услуги
      • Лицензии 1С-Битрикс
        • Облачный сервис Битрикс24 —
        • Коробочная версия Битрикс24 —
        • Подписка Битрикс24.Маркет Плюс
      • Внедрение CRM
      • Доработка корпоративных порталов Битрикс24
      • Техническое сопровождение
      • Перенос Битрикс24 из облака в коробку
      • Сайты на 1С-Битрикс24
      Проекты
      • Государственные организации
      • Управление бизнесом
      • Спорт
      • Автомобильный бизнес
      Акции
      Новости
      Компания
      • О компании
      • Сертификаты
      • Карьера
      • Разработка ПО
      Контакты
        7sites - внедрение Битрикс24
        7sites - внедрение Битрикс24
        • Услуги
          • Назад
          • Услуги
          • Лицензии 1С-Битрикс
            • Назад
            • Лицензии 1С-Битрикс
            • Облачный сервис Битрикс24
            • Коробочная версия Битрикс24
            • Подписка Битрикс24.Маркет Плюс
          • Внедрение CRM
          • Доработка корпоративных порталов Битрикс24
          • Техническое сопровождение
          • Перенос Битрикс24 из облака в коробку
          • Сайты на 1С-Битрикс24
        • Проекты
          • Назад
          • Проекты
          • Государственные организации
          • Управление бизнесом
          • Спорт
          • Автомобильный бизнес
        • Акции
        • Новости
        • Компания
          • Назад
          • Компания
          • О компании
          • Сертификаты
          • Карьера
          • Разработка ПО
        • Контакты
        • +7 (495) 118-30-89
        info@7sites.ru
        г. Пермь, ш. Космонавтов 111, к. 10
        • Вконтакте
        • Facebook
        • Twitter
        • Telegram
        • Главная
        • Пресс-центр
        • Полезное
        • Получение списка всех подразделов инфоблока в Битрикс24: метод CIBlockSection::GetList с древовидной навигацией

        Получение списка всех подразделов инфоблока в Битрикс24: метод CIBlockSection::GetList с древовидной навигацией

        20 апреля 2026
        Полезное

        Введение

        При разработке на коробочной версии Битрикс24 часто возникает необходимость программно получить список всех подразделов (подкатегорий) определённого раздела инфоблока. В отличие от простой фильтрации по SECTION_ID, древовидная структура инфоблоков требует использования полей LEFT_MARGIN и RIGHT_MARGIN для получения всех вложенных элементов независимо от глубины вложенности. Основным инструментом для этого является метод CIBlockSection::GetList в связке с навигацией по дереву.

        Важное отличие: фильтр по SECTION_ID vs навигация по LEFT_MARGIN / RIGHT_MARGIN

        Ключевая особенность: простая фильтрация по SECTION_ID возвращает только прямых потомков раздела (первый уровень вложенности). Для получения всех подразделов (на любую глубину) необходимо использовать поля LEFT_MARGIN и RIGHT_MARGIN, которые реализуют механизм Nested Sets (вложенные множества).

        Подход Что возвращает Глубина
        SECTION_ID = $parentId Только прямые подразделы 1 уровень
        LEFT_MARGIN > parent.LEFT_MARGIN и RIGHT_MARGIN < parent.RIGHT_MARGIN Все подразделы на любой глубине Все уровни

        Область применения и ключевые сущности

        Метод CIBlockSection::GetList с фильтрацией по LEFT_MARGIN и RIGHT_MARGIN используется для получения иерархической структуры разделов инфоблока. Понимание этой связки необходимо при:

        • Построении многоуровневых меню — вывод всех категорий с учётом вложенности
        • Экспорте каталога — получение полной структуры категорий товаров
        • Обработке всех элементов раздела — рекурсивный обход всех подразделов
        • Миграции данных — копирование структуры разделов
        • SEO-генерации — создание ЧПУ для всех уровней вложенности
        • Фильтрации товаров — показ товаров из раздела и всех его подразделов

        Ключевые сущности:

        Таблица / Класс Описание
        b_iblock_section Таблица с разделами инфоблоков
        CIBlockSection Класс для работы с разделами
        LEFT_MARGIN Левая граница раздела в дереве (Nested Sets)
        RIGHT_MARGIN Правая граница раздела в дереве (Nested Sets)
        DEPTH_LEVEL Уровень вложенности (1 — корень, 2 — первый подраздел и т.д.)

        Параметры метода CIBlockSection::GetList

        Метод имеет следующую сигнатуру:

        php
        public static function GetList($arOrder = [], $arFilter = [], $bIncCnt = false, $arSelect = [])

        Параметр $arOrder (сортировка)

        Определяет порядок сортировки разделов:

        php
        $arOrder = ['left_margin' => 'ASC'];  // сортировка по левой границе (древовидный порядок)

        Доступные ключи: ID, NAME, SORT, LEFT_MARGIN, RIGHT_MARGIN, DEPTH_LEVEL, TIMESTAMP_X и др.

        Параметр $arFilter (фильтрация)

        Для получения всех подразделов используются следующие ключи:

        Ключ Описание Пример
        IBLOCK_ID ID инфоблока $arParentSection['IBLOCK_ID']
        >LEFT_MARGIN Левая граница больше родительской $arParentSection['LEFT_MARGIN']
        <RIGHT_MARGIN Правая граница меньше родительской $arParentSection['RIGHT_MARGIN']
        >DEPTH_LEVEL Глубина больше родительской $arParentSection['DEPTH_LEVEL']
        SECTION_ID ID родительского раздела (только прямые потомки) $parentId

        Практические примеры

        Пример 1. Базовое получение всех подразделов (как в вашем коде)

        php
        if (\Bitrix\Main\Loader::includeModule('iblock')) {
            // Получаем родительский раздел с ID = 4
            $rsParentSection = CIBlockSection::GetByID(4);
            
            if ($arParentSection = $rsParentSection->GetNext()) {
                // Фильтр для получения всех подразделов на любую глубину
                $arFilter = [
                    'IBLOCK_ID'     => $arParentSection['IBLOCK_ID'],
                    '>LEFT_MARGIN'  => $arParentSection['~LEFT_MARGIN'],
                    '<RIGHT_MARGIN' => $arParentSection['~RIGHT_MARGIN'],
                    '>DEPTH_LEVEL'  => $arParentSection['DEPTH_LEVEL']
                ];
                
                $rsSect = CIBlockSection::GetList(['left_margin' => 'ASC'], $arFilter);
                
                while ($arSect = $rsSect->GetNext()) {
                    // Выводим ID каждого подраздела
                    echo "<pre>"; print_r($arSect['ID']); echo "</pre>";
                }
            }
        }

        Пример 2. Функция для получения всех подразделов с данными

        php
        /**
         * Получает все подразделы раздела инфоблока (рекурсивно, на любую глубину)
         * 
         * @param int $sectionId ID родительского раздела
         * @return array Массив подразделов с полной информацией
         */
        function getAllSubsections(int $sectionId): array
        {
            if (!\Bitrix\Main\Loader::includeModule('iblock')) {
                return [];
            }
            
            $subsections = [];
            
            // Получаем родительский раздел
            $rsParent = CIBlockSection::GetByID($sectionId);
            $parent = $rsParent->Fetch();
            
            if (!$parent) {
                return [];
            }
            
            // Фильтр для всех подразделов (любой глубины)
            $filter = [
                'IBLOCK_ID' => $parent['IBLOCK_ID'],
                '>LEFT_MARGIN' => $parent['LEFT_MARGIN'],
                '<RIGHT_MARGIN' => $parent['RIGHT_MARGIN'],
                '>DEPTH_LEVEL' => $parent['DEPTH_LEVEL']
            ];
            
            $rsSections = CIBlockSection::GetList(
                ['LEFT_MARGIN' => 'ASC'],
                $filter,
                false,
                ['ID', 'NAME', 'CODE', 'DEPTH_LEVEL', 'LEFT_MARGIN', 'RIGHT_MARGIN', 'SECTION_PAGE_URL']
            );
            
            while ($section = $rsSections->Fetch()) {
                $subsections[] = [
                    'ID' => $section['ID'],
                    'NAME' => $section['NAME'],
                    'CODE' => $section['CODE'],
                    'DEPTH_LEVEL' => $section['DEPTH_LEVEL'],
                    'URL' => $section['SECTION_PAGE_URL']
                ];
            }
            
            return $subsections;
        }
        
        // Использование
        $subsections = getAllSubsections(4);
        echo '<pre>'; print_r($subsections); echo '</pre>';

        Пример 3. Сравнение: SECTION_ID vs LEFT_MARGIN/RIGHT_MARGIN

        php
        $parentSectionId = 4;
        
        // ❌ Только прямые подразделы (первый уровень)
        $filterDirect = ['IBLOCK_ID' => 1, 'SECTION_ID' => $parentSectionId];
        $rsDirect = CIBlockSection::GetList(['SORT' => 'ASC'], $filterDirect);
        echo "Прямые подразделы (SECTION_ID):\n";
        while ($sect = $rsDirect->Fetch()) {
            echo "ID: {$sect['ID']}, NAME: {$sect['NAME']}, DEPTH: {$sect['DEPTH_LEVEL']}\n";
        }
        
        // ✅ Все подразделы на любую глубину (через LEFT_MARGIN/RIGHT_MARGIN)
        $rsParent = CIBlockSection::GetByID($parentSectionId);
        $parent = $rsParent->Fetch();
        
        if ($parent) {
            $filterAll = [
                'IBLOCK_ID' => $parent['IBLOCK_ID'],
                '>LEFT_MARGIN' => $parent['LEFT_MARGIN'],
                '<RIGHT_MARGIN' => $parent['RIGHT_MARGIN'],
                '>DEPTH_LEVEL' => $parent['DEPTH_LEVEL']
            ];
            $rsAll = CIBlockSection::GetList(['LEFT_MARGIN' => 'ASC'], $filterAll);
            echo "\nВсе подразделы (LEFT_MARGIN/RIGHT_MARGIN):\n";
            while ($sect = $rsAll->Fetch()) {
                $indent = str_repeat('--', $sect['DEPTH_LEVEL'] - $parent['DEPTH_LEVEL']);
                echo "{$indent} ID: {$sect['ID']}, NAME: {$sect['NAME']}, DEPTH: {$sect['DEPTH_LEVEL']}\n";
            }
        }

        Пример 4. Получение подразделов с построением дерева

        php
        function getSubsectionsTree(int $sectionId): array
        {
            if (!\Bitrix\Main\Loader::includeModule('iblock')) {
                return [];
            }
            
            $rsParent = CIBlockSection::GetByID($sectionId);
            $parent = $rsParent->Fetch();
            
            if (!$parent) {
                return [];
            }
            
            $filter = [
                'IBLOCK_ID' => $parent['IBLOCK_ID'],
                '>LEFT_MARGIN' => $parent['LEFT_MARGIN'],
                '<RIGHT_MARGIN' => $parent['RIGHT_MARGIN']
            ];
            
            $rsSections = CIBlockSection::GetList(
                ['LEFT_MARGIN' => 'ASC'],
                $filter,
                false,
                ['ID', 'NAME', 'DEPTH_LEVEL', 'LEFT_MARGIN', 'RIGHT_MARGIN']
            );
            
            // Строим дерево
            $tree = [];
            $stack = [];
            $currentDepth = $parent['DEPTH_LEVEL'];
            
            while ($section = $rsSections->Fetch()) {
                $level = $section['DEPTH_LEVEL'];
                $node = [
                    'ID' => $section['ID'],
                    'NAME' => $section['NAME'],
                    'CHILDREN' => []
                ];
                
                if ($level == $currentDepth + 1) {
                    // Прямой потомок текущего узла
                    $stack[] = &$node;
                } else {
                    // Возвращаемся на уровень выше
                    while (count($stack) > 0 && $stack[count($stack) - 1]['DEPTH_LEVEL'] >= $level) {
                        array_pop($stack);
                    }
                    if (count($stack) > 0) {
                        $stack[count($stack) - 1]['CHILDREN'][] = &$node;
                    }
                    $stack[] = &$node;
                }
                
                $node['DEPTH_LEVEL'] = $level;
                
                if (count($stack) == 1) {
                    $tree[] = &$node;
                }
            }
            
            return $tree;
        }

        Пример 5. Получение ID всех подразделов (включая вложенные)

        php
        function getAllSubsectionIds(int $sectionId): array
        {
            if (!\Bitrix\Main\Loader::includeModule('iblock')) {
                return [];
            }
            
            $rsParent = CIBlockSection::GetByID($sectionId);
            $parent = $rsParent->Fetch();
            
            if (!$parent) {
                return [];
            }
            
            $filter = [
                'IBLOCK_ID' => $parent['IBLOCK_ID'],
                '>LEFT_MARGIN' => $parent['LEFT_MARGIN'],
                '<RIGHT_MARGIN' => $parent['RIGHT_MARGIN']
            ];
            
            $ids = [];
            $rsSections = CIBlockSection::GetList(['LEFT_MARGIN' => 'ASC'], $filter, false, ['ID']);
            
            while ($section = $rsSections->Fetch()) {
                $ids[] = $section['ID'];
            }
            
            return $ids;
        }
        
        // Использование: получим ID всех подразделов раздела 4
        $allSubIds = getAllSubsectionIds(4);
        echo "ID всех подразделов: " . implode(', ', $allSubIds);

        Пример 6. Проверка, является ли раздел родительским для другого

        php
        function isParentSection(int $parentId, int $childId): bool
        {
            if (!\Bitrix\Main\Loader::includeModule('iblock')) {
                return false;
            }
            
            $rsParent = CIBlockSection::GetByID($parentId);
            $parent = $rsParent->Fetch();
            
            $rsChild = CIBlockSection::GetByID($childId);
            $child = $rsChild->Fetch();
            
            if (!$parent || !$child) {
                return false;
            }
            
            // Проверяем, что разделы в одном инфоблоке
            if ($parent['IBLOCK_ID'] != $child['IBLOCK_ID']) {
                return false;
            }
            
            // Дочерний раздел находится внутри границ родительского
            return ($parent['LEFT_MARGIN'] < $child['LEFT_MARGIN'] && 
                    $parent['RIGHT_MARGIN'] > $child['RIGHT_MARGIN']);
        }
        
        // Использование
        if (isParentSection(4, 10)) {
            echo "Раздел 10 является подразделом раздела 4";
        }

        Пример 7. Получение элементов из раздела со всеми подразделами

        php
        function getElementsFromSectionWithSubsections(int $sectionId): array
        {
            if (!\Bitrix\Main\Loader::includeModule('iblock')) {
                return [];
            }
            
            // Получаем ID всех подразделов
            $subsectionIds = getAllSubsectionIds($sectionId);
            
            // Добавляем сам родительский раздел
            $allSectionIds = array_merge([$sectionId], $subsectionIds);
            
            // Получаем элементы из всех этих разделов
            $filter = [
                'IBLOCK_ID' => 1,
                'SECTION_ID' => $allSectionIds,
                'INCLUDE_SUBSECTIONS' => 'Y'  // Важно! Включает элементы из подразделов
            ];
            
            $elements = [];
            $rsElements = CIBlockElement::GetList(
                ['SORT' => 'ASC'],
                $filter,
                false,
                false,
                ['ID', 'NAME', 'IBLOCK_SECTION_ID']
            );
            
            while ($element = $rsElements->Fetch()) {
                $elements[] = $element;
            }
            
            return $elements;
        }

        Структура таблиц и принцип Nested Sets

        sql
        -- b_iblock_section (разделы)
        -- ID, IBLOCK_ID, NAME, DEPTH_LEVEL, LEFT_MARGIN, RIGHT_MARGIN
        
        -- Принцип работы LEFT_MARGIN / RIGHT_MARGIN:
        -- Корневой раздел: LEFT_MARGIN = 1, RIGHT_MARGIN = 10
        --   Подраздел 1: LEFT_MARGIN = 2, RIGHT_MARGIN = 5
        --     Подподраздел: LEFT_MARGIN = 3, RIGHT_MARGIN = 4
        --   Подраздел 2: LEFT_MARGIN = 6, RIGHT_MARGIN = 9
        --     Подподраздел: LEFT_MARGIN = 7, RIGHT_MARGIN = 8

        Альтернативные методы

        Метод Описание
        CIBlockSection::GetByID() Получение одного раздела по ID
        CIBlockSection::GetTreeList() Получение дерева разделов (устаревший)
        CIBlockSection::GetNavChain() Получение цепочки навигации (хлебные крошки)
        CIBlockSection::GetSectionElementsCount() Получение количества элементов в разделе

        Особенности и рекомендации

        1. Обязательное подключение модуля: Перед вызовом методов необходимо подключить модуль iblock через CModule::IncludeModule('iblock').

        2. Использование ~LEFT_MARGIN vs LEFT_MARGIN: В вашем коде используется $arParentSection['~LEFT_MARGIN'] (с тильдой). Тильда означает получение значения в исходном формате (без HTML-экранирования). Для числовых полей это не критично, но хорошая практика.

        3. Важность сортировки по LEFT_MARGIN: При получении дерева разделов всегда сортируйте по LEFT_MARGIN ASC — это гарантирует правильный порядок обхода.

        4. Фильтр >DEPTH_LEVEL: Используйте этот фильтр, если хотите исключить сам родительский раздел из выборки.

        5. Производительность: Запросы с LEFT_MARGIN и RIGHT_MARGIN очень быстрые, так как эти поля индексированы. Это гораздо эффективнее рекурсивных запросов.

        6. Кеширование: При частых запросах структуры разделов используйте кеширование, например, через CIBlockSection::GetList([...], [...], false, false, ['CACHE_TIME' => 3600]).

        7. Глубина вложенности: Теоретически не ограничена, но практически в Битрикс редко превышает 10 уровней.

        Заключение

        CIBlockSection::GetList с фильтрацией по LEFT_MARGIN и RIGHT_MARGIN — это основной и наиболее эффективный способ получения всех подразделов раздела инфоблока в коробочной версии Битрикс24. В отличие от простой фильтрации по SECTION_ID, которая возвращает только прямых потомков, навигация по Nested Sets позволяет получить все вложенные подразделы на любую глубину за один запрос. Понимание этого подхода необходимо каждому разработчику, который работает с иерархическими структурами: каталогами товаров, меню, древовидными справочниками и другими многоуровневыми данными.

        Начните сотрудничество с индивидуальной консультации по подбору инструментов и услуг.
        Заказать услугу

        Подписаться на
        рассылку

        Будьте в курсе последних новостей отрасли

        Подписаться
        • Комментарии
        Загрузка комментариев...
        Назад к списку
        Услуги
        Лицензии 1С-Битрикс
        Внедрение CRM
        Доработка корпоративных порталов Битрикс24
        Техническое сопровождение
        Перенос Битрикс24 из облака в коробку
        Сайты на 1С-Битрикс24
        Компания
        О компании
        Сертификаты
        Карьера
        Разработка ПО
        Проекты
        Новости
        Контакты
        Подписка на рассылку
        +7 (495) 118-30-89
        Заказать звонок
        info@7sites.ru
        г. Пермь, ш. Космонавтов 111, к. 10
        • Вконтакте
        • Facebook
        • Twitter
        • Telegram
        Политика конфиденциальности
        © 2009-2026 ООО "7 САЙТОВ" (с) Все права защищены.
        Заказать звонок
        Написать сообщение
        Ближайший офис