Передо мной стояла задача: сделать древовидное меню с глубиной вложения до 5 каталогов.
Решена она была поиском и доработкой подходящего решения.
Для того чтобы получить древовидное меню необходима рекурсивная функция, которая будет обходить все дерево подкатегорий и строить на них ссылки с учетом родительских элементов.
Было найдено просто отличное решение http://yunaliev.ru/2014/01/razdely-infobloka-v-vide-massiva-1s-bitriks/
Далее выдержки из текста и мои доработки.
Пошаговый перебор элементов дерева по связям между узлами-предками и узлами-потомками называется обходом дерева. Зачастую, операция может быть выполнена переходом указателя по отдельным узлам. Обход, при котором каждый узел-предок просматривается прежде его потомков называется предупорядоченным обходом или обходом в прямом порядке (pre-order walk), а когда просматриваются сначала потомки, а потом предки, то обход называется поступорядоченным обходом или обходом в обратном порядке (post-order walk). Существует также симметричный обход, при котором посещается сначала левое поддерево, затем узел, затем — правое поддерево, и обход в ширину, при котором узлы посещаются уровень за уровнем (N-й уровень дерева — множество узлов с высотой N). Каждый уровень обходится слева направо.
По умолчанию используется, обход в ширину.
В результате из подобного массива получается такое меню.
----- CODE -----
$rs_Section = CIBlockSection::GetList(array('left_margin' => 'asc'), array('IBLOCK_ID' => 3, 'ACTIVE' => 'Y'));
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'],
'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'],
);
}
$rs_Section = CIBlockSection::GetList(
array('DEPTH_LEVEL' => 'desc'),
array('IBLOCK_ID' => 3, 'ACTIVE' => 'Y'),
false,
array('ID', 'NAME', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL', 'SORT', 'SECTION_PAGE_URL')
);
$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");
$page_url = $APPLICATION->GetCurPage();// текущий URL страницы, в функции __recursivRenderMenu идет сравнение с URL в пункте меню. Если совпадает, подсвечиваем.
function __recursivRenderMenu($ar_Items, $nesting_lvl = 0, $page_url)
{
$html = '';
// echo "<pre>";
// print_r($ar_Items);
// echo "</pre>";
foreach ($ar_Items as $ar_Value)
{
if( count($ar_Value['SUB_SECTION']) > 0 )
{
if($nesting_lvl == 0)
{
$margin = 0;
}
else
{
$margin = $nesting_lvl*20;
}
$html .= '<ul class="lvl_'.$nesting_lvl.'" style="margin-left:'.$margin.'px">';
$html .= '<li>';
if($page_url == $ar_Value['SECTION_PAGE_URL'])
{
$html .= "<a style='color: #53b981' href='".$ar_Value['SECTION_PAGE_URL']."'>";
}
else
{
$html .= "<a href='".$ar_Value['SECTION_PAGE_URL']."'>";
}
$html .= $ar_Value['NAME'];
$html .= "</a>";
# рекурсивный вызов функции
$html .= __recursivRenderMenu($ar_Value['SUB_SECTION'], $nesting_lvl+1, $page_url);
$html .= '</li>';
$html .= '</ul>';
}
else
{
$html .= '<li class="mur-mur lvl_'.$nesting_lvl.'">';
if($page_url == $ar_Value['SECTION_PAGE_URL'])
{
$html .= '<a style="color: #53b981" href="'.$ar_Value['SECTION_PAGE_URL'].'">'.$ar_Value['NAME'].'</a>';
}
else
{
$html .= '<a href="'.$ar_Value['SECTION_PAGE_URL'].'">'.$ar_Value['NAME'].'</a>';
}
$html .= '</li>';
}
}
return $html;
}
----- /CODE -----