По умолчанию CIBlockSection::GetList() возвращает секции в порядке обхода в ширину — плоским списком. Иногда нужна либо вложенная структура для рекурсивного рендера меню, либо плоский массив с явными метаданными иерархии для построения <select>.
Способ 1 — плоский массив с метаданными иерархии
Сортируем по left_margin, получаем поля DEPTH_LEVEL, LEFT_MARGIN, RIGHT_MARGIN, IBLOCK_SECTION_ID:
$rs_Section = CIBlockSection::GetList(array('left_margin' => 'asc'), array('IBLOCK_ID' => 8));
while ( $ar_Section = $rs_Section->Fetch() )
{
$ar_Result[] = array(
'ID' => $ar_Section['ID'],
'NAME' => $ar_Section['NAME'],
'IBLOCK_SECTION_ID' => $ar_Section['IBLOCK_SECTION_ID'],
'LEFT_MARGIN' => $ar_Section['LEFT_MARGIN'],
'RIGHT_MARGIN' => $ar_Section['RIGHT_MARGIN'],
'DEPTH_LEVEL' => $ar_Section['DEPTH_LEVEL'],
);
}Вывод в виде <select> с отступами по уровню вложенности:
<select>
<option> - Выбрать - </option>
<?
foreach( $ar_Result as $ar_Value )
{
$s = '';
for($i = 1; $i <= $ar_Value['DEPTH_LEVEL']; $i++ )
$s .= '.';
$s .= ' '.$ar_Value['NAME'];
?><option value="<?=$ar_Value['ID']?>"><?=$s?></option><?
}
?>
</select>Способ 2 — вложенный массив (дерево)
Алгоритм: сортируем секции по DEPTH_LEVEL убыванием, затем итерируем от максимального уровня вниз — каждый раздел добавляем в SUB_SECTION своего родителя и удаляем из основного массива:
$rs_Section = CIBlockSection::GetList(
array('DEPTH_LEVEL' => 'desc'),
$ar_Filter,
false,
array('ID', 'NAME', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL', 'SORT')
);
$ar_SectionList = array();
$ar_DepthLavel = array();
while($ar_Section = $rs_Section->GetNext(true, false))
{
$ar_SectionList[$ar_Section['ID']] = $ar_Section;
$ar_DepthLavel[] = $ar_Section['DEPTH_LEVEL'];
}
$ar_DepthLavelResult = array_unique($ar_DepthLavel);
rsort($ar_DepthLavelResult);
$i_MaxDepthLevel = $ar_DepthLavelResult[0];
for( $i = $i_MaxDepthLevel; $i > 1; $i-- )
{
foreach ( $ar_SectionList as $i_SectionID => $ar_Value )
{
if( $ar_Value['DEPTH_LEVEL'] == $i )
{
$ar_SectionList[$ar_Value['IBLOCK_SECTION_ID']]['SUB_SECTION'][] = $ar_Value;
unset( $ar_SectionList[$i_SectionID] );
}
}
}
function __sectionSort($a, $b)
{
if ($a['SORT'] == $b['SORT']) {
return 0;
}
return ($a['SORT'] < $b['SORT']) ? -1 : 1;
}
usort($ar_SectionList, "__sectionSort");Рекурсивный вывод дерева в виде вложенных <ul>:
function __recursivRenderMenu($ar_Items)
{
foreach ($ar_Items as $ar_Value)
{
if( count($ar_Value['SUB_SECTION']) > 0 )
{
echo '<ul>';
echo '<li>';
echo $ar_Value['NAME'];
echo '<ul>';
echo __recursivRenderMenu($ar_Value['SUB_SECTION']);
echo '</ul>';
echo '</li>';
echo '</ul>';
}
else
{
echo '<li>'.$ar_Value['NAME'].'</li>';
}
}
}
echo __recursivRenderMenu($ar_SectionList);