yunaweb/bitrix-section-tree

Build/flatten section trees from flat lists (e.g. Bitrix CIBlockSection / D7 SectionTable rows) without hierarchy hacks.

Maintainers

Package info

github.com/remitmaster/bitrix-section-tree

pkg:composer/yunaweb/bitrix-section-tree

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-20 21:20 UTC

This package is auto-updated.

Last update: 2026-07-20 21:27:15 UTC


README

Собрать дерево разделов из плоского списка (например, из \Bitrix\Iblock\SectionTable::getList() или CIBlockSection::GetList()) — без ручного unset/usort-хака. Работает с обычными PHP-массивами, к Bitrix не привязан.

Установка

composer require yunaweb/bitrix-section-tree

Использование

Плоский список → дерево

use Yunaweb\SectionTree\SectionTree;

$sections = [
    ['ID' => 1, 'IBLOCK_SECTION_ID' => null, 'NAME' => 'Каталог'],
    ['ID' => 2, 'IBLOCK_SECTION_ID' => 1, 'NAME' => 'Телефоны'],
    ['ID' => 3, 'IBLOCK_SECTION_ID' => 1, 'NAME' => 'Ноутбуки'],
];

$tree = SectionTree::toTree($sections);
// $tree[0]['NAME'] === 'Каталог'
// $tree[0]['CHILDREN'][0]['NAME'] === 'Телефоны'

Дерево → плоский список с глубиной и путём

$flat = SectionTree::toFlat($tree);
// $flat[1]['DEPTH'] === 1
// $flat[1]['PATH'] === [1, 2]

Цепочка предков (breadcrumbs)

$chain = SectionTree::breadcrumbs($sections, 2);
// array_column($chain, 'NAME') === ['Каталог', 'Телефоны']

С Bitrix D7

use Bitrix\Iblock\SectionTable;
use Yunaweb\SectionTree\SectionTree;

$rows = SectionTable::getList([
    'filter' => ['IBLOCK_ID' => 8],
    'select' => ['ID', 'IBLOCK_SECTION_ID', 'NAME', 'SORT'],
])->fetchAll();

$tree = SectionTree::toTree($rows);

Пример: <select> с отступами по уровню вложенности

$flat = SectionTree::toFlat(SectionTree::toTree($sections));

foreach ($flat as $section) {
    $indent = str_repeat('', $section['DEPTH']);
    echo '<option value="' . htmlspecialchars((string) $section['ID']) . '">'
        . $indent . htmlspecialchars($section['NAME']) . "</option>\n";
}

Пример: рекурсивное меню (вложенные <ul>)

function renderMenu(array $items): string
{
    $html = '<ul>';
    foreach ($items as $item) {
        $html .= '<li>' . htmlspecialchars($item['NAME']);
        if ($item['CHILDREN'] !== []) {
            $html .= renderMenu($item['CHILDREN']);
        }
        $html .= '</li>';
    }

    return $html . '</ul>';
}

echo renderMenu(SectionTree::toTree($sections));

Настраиваемые ключи

Если поля называются не как в Bitrix (ID / IBLOCK_SECTION_ID), передайте свои имена:

SectionTree::toTree($items, idKey: 'id', parentKey: 'parent_id');

Ошибки

Отсутствующий idKey в элементе, дублирующийся id, циклическая ссылка на родителя или breadcrumbs() с несуществующим id бросают Yunaweb\SectionTree\Exception\SectionTreeException.

Ограничения

  • Библиотека сама ничего не экранирует — NAME и другие поля из вашего источника данных попадают в вывод как есть. Перед выводом в HTML используйте htmlspecialchars() (см. примеры выше).
  • toTree()/toFlat() не рассчитаны на непроверенные данные с неограниченной глубиной вложенности: на цепочке из нескольких тысяч уровней проверка циклов и подсчёт PATH работают за O(n²) по времени/памяти. Для типичной глубины разделов каталога (единицы–десятки уровней) это не заметно, но для импорта из недоверенного источника с неизвестной глубиной ограничьте её до вызова библиотеки.

Тесты

composer install
vendor/bin/phpunit

Лицензия

MIT