Получение иерархии разделов

24.09.2013

Приведу небольшой примерчик как одним запросом и одним циклом получить иерархию разделов в виде:

Array
(
    [ROOT] => Array
        (
            [CHILD] => Array
                (
                    [12] => Array
                        (
                            [ID] => 12
                            [~ID] => 12
                            [NAME] => Раздел с ид 12
                            [~NAME] => Раздел с ид 12 
                            [DEPTH_LEVEL] => 1
                            [~DEPTH_LEVEL] => 1
                            [CHILD] => Array
                                (
                                    [63] => Array
                                        (
                                            [ID] => 63
                                            [~ID] => 63
                                            .............
                                            [CHILD] => Array
                                                (
                                                ........
                                                )
                                        )
                                     .......
                                    [63] => Array
                                        (
                                            [ID] => 63
                                            [~ID] => 63
                                            .............
                                        )
                                     .......
                                )
                        )
                 ..............
                )
        )
)

На мой взгляд, с такой структурой работать в большинстве случаев удобнее, чем со списком, отсортированном по LEFT_MARGIN

Итак код:


$arFilter = array(		
    'ACTIVE' => 'Y',
    'IBLOCK_ID' => $arParams['IBLOCK_ID'],
    'GLOBAL_ACTIVE'=>'Y',
);
$arSelect = array('IBLOCK_ID','ID','NAME','DEPTH_LEVEL','IBLOCK_SECTION_ID');
$arOrder = array('DEPTH_LEVEL'=>'ASC','SORT'=>'ASC');
$rsSections = CIBlockSection::GetList($arOrder, $arFilter, false, $arSelect);
$sectionLinc = array();
$arResult['ROOT'] = array();
$sectionLinc[0] = &$arResult['ROOT'];
while($arSection = $rsSections->GetNext()) {
    $sectionLinc[intval($arSection['IBLOCK_SECTION_ID'])]['CHILD'][$arSection['ID']] = $arSection;
    $sectionLinc[$arSection['ID']] = &$sectionLinc[intval($arSection['IBLOCK_SECTION_ID'])]['CHILD'][$arSection['ID']];
}
unset($sectionLinc);

Если мы получаем только активные элементы, то важно указать в фильтре 'GLOBAL_ACTIVE'=>'Y', иначе мы можем получить активный элемент с неактивным предком, и его некуда будет определить в иерархию.

В $arSelect нужно не забыть указать IBLOCK_SECTION_ID, иначе иерархию построить не получится

Первое поле в сортировке $arOrder должно быть 'DEPTH_LEVEL'=>'ASC', так как иерархия строится от предков к потомкам

Построение иерархии происходит через массив ссылок $sectionLinc

.

Комментарии:

Михаил

04.04.2014 10:56:23

Ох! Огромное Вам спасибо, коллега!
Очень выручили!

Мистер Игрек

08.05.2014 05:38:22

Это реально круто. Вот что значит красивый код!

cryptic

12.05.2014 20:20:14

Подскажите пожалуйста, где узнать значение IBLOCK_SECTION_ID. А то иерархии не получается :(

Максим

13.05.2014 06:16:08

IBLOCK_SECTION_ID не надо узнавать, он достается из базы, это ID родительского раздела.
Приведенный выше код полностью рабочий, нужно только чтобы $arParams['IBLOCK_ID'] содержал ID необходимого инфоблока.

Юрий

20.10.2014 13:32:00

У вас в строчке

$sectionLinc[$arSection['ID']] = &$sectionLinc[intval($arSection['IBLOCK_SECTION_ID'])]['CHILD'][$ar_result['ID']];


ошибка, тут вместо $ar_result похоже надо $arSection

Максим

20.10.2014 13:49:48

Юрий, вы правы! Спасибо огромное! Исправил пример.

Алексей

25.11.2014 16:12:59

$sectionLinc[$arSection['ID']] = &$sectionLinc[intval($arSection['IBLOCK_SECTION_ID'])]['CHILD'][$arSection['ID']];
Получается что вложенность у Вас ограничена 2-мя уровнями, так как если в массиве ['CHILD'] будут элементы со своими потомками, то ссылка на них должна вести уже на 3-й уровень дерева, но в данном способе она все-рвоно будет вести на второй.

Максим

25.11.2014 18:22:54

Нет, количество уровней не ограничено. Иерархия собирается в $arResult['ROOT'], а $sectionLinc - это массив ссылок. Попробуйте.

Дмитрий

22.06.2015 18:03:24

Максим, данная конструкция работает если нам нужно вывести сразу все дерево. Например, меню каталога. А если использовать это для вывода разделов в каталоге, то это работает не корректно. Поясню. Допустим в корневой странице каталога мы выводим список разделов первого уровня. Здесь все выводится хорошо. Ваш скрипт работает. Но стоит перейти во второй уровень то ничего не собирается в root. А все потому что IBLOCK_SECTION_ID у первого раздела уже будет не пустой. То есть intval($arSection['IBLOCK_SECTION_ID']) не будет равно никак в этом случае.

как вариант сделал так:

Вместо:

$sectionLinc[0] = &$arResult['ROOT'];

Написал так:

$sectionLink[intval($arResult['SECTIONS'][0]['IBLOCK_SECTION_ID'])] = &$arStructured['ROOT'];

Так работает на всех уровнях вложенности, не обязательно от корня. Может кому пригодится

Елена

27.06.2015 21:52:14

Запятую в конце строки 7 забыли :)

Максим

29.06.2015 12:50:54

Елена, спасибо! Вернул точку с запятой на её законное место!

mbh

05.01.2016 10:51:10

Я начинающий в битриксе, подскажите пожалуйста, где следует размещать этот код ?

Константин

13.02.2016 14:16:26

Также можно сделать вывод разделов и элементов в виде дерева.
Компонент http://marketplace.1c-bitrix.ru/solutions/twozebras.infoblocktree/ в помощь!

eugene

09.06.2016 10:34:06

Подскажите, пожалуйста, что нужно добавить в данный код, чтобы кроме подразделов выводились и элементы подразделов?

Максим

09.06.2016 14:40:31

eugene, код который вам нужен можете найти здесь: Меню из разделов инфоблока с элементами

Елена

21.03.2017 09:37:43

Спасибо! Да добавится благодати к вашей карме)))

Денис

15.09.2017 18:32:58

Спасибо большое. Очень полезная статья и очень помогла!

Юрий

29.12.2018 14:45:42

Спасибо большое! Очень помогло ваше решение! А я уже несколько дней костыли всё какие то писал )))

Денис

20.02.2019 13:55:44

А как в массив с подразделами запихнуть все элементы раздела?
Предположим, нужно вывести все элементы подразделов подразделов главного родителя?

Алёна

18.03.2020 15:22:04

До слёз.... Как же долго я билась над задачей и как удачно я нашла эту запись!
Искренне благодарна автору!
__________________
Кстати, если кому нужен определенный путь из разделов, то в $arFilter нужно добавить все id разделов со вложенностью:
`
$arFilter = array(
'ACTIVE' => 'Y',
'IBLOCK_ID' => $arParams['IBLOCK_ID'],
'GLOBAL_ACTIVE'=>'Y',
'ID' => [ массив id разделов ]
);
`

Михаил

18.04.2020 16:13:44

Добрый день!
Отличный код
Только не пойму, если оставить unset($sectionLinc) то ничего не выводится
если без unset($sectionLinc) то данные дублируются
В чем может быть дело?

Ильдар

16.12.2020 12:07:02

Михаил, выводите не $sectionLinc, а массив $arResult

Дмитрий

19.02.2021 10:47:04

Добрый день,
Благодарю за за решение.

Подскажите, сейчас дерево строится от корня инфоблока, а как сделать чтобы дерево можно было строить от заданной секции?

Денис

21.05.2021 11:01:31

Like!

BOSS

20.08.2021 16:41:47

СПасибо! топ!

Леонид

14.08.2022 17:49:37

Ни как не пойму как дочерний элемент оказывается в массиве ссылок с индексом 0. Могли бы вы объяснить как происходит построение ирархии в массиве ссылок с индексом 0?

Александр

09.11.2023 17:06:44

а не проще CIBlockSection::GetList?
https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblocksection/gettreelist.php

вашим способом замечаетесь потом получившийся массив перебирать

Оставить комментарий:

Представьтесь пожалуйста:
Электронная почта:
Электронный адрес не публикуются
Текст сообщения:
Для подсветки кода, оборачивайте ваш код в теги <code></code>
Введите 5 цифр с картинки:

Рекомендую:

Поделюсь промокодами для хостинга TimeWeb!

Поддержать проект: