Бортовой журнал Ктулху

Древовидное меню в Битриксе

Передо мной стояла задача: сделать древовидное меню с глубиной вложения до 5 каталогов.

Решена она была поиском и доработкой подходящего решения.

Для того чтобы получить древовидное меню необходима рекурсивная функция, которая будет обходить все дерево подкатегорий и строить на них ссылки с учетом родительских элементов.

Было найдено просто отличное решение http://yunaliev.ru/2014/01/razdely-infobloka-v-vide-massiva-1s-bitriks/

Далее выдержки из текста и мои доработки.

Пошаговый перебор элементов дерева по связям между узлами-предками и узлами-потомками называется обходом дерева. Зачастую, операция может быть выполнена переходом указателя по отдельным узлам. Обход, при котором каждый узел-предок просматривается прежде его потомков называется предупорядоченным обходом или обходом в прямом порядке (pre-order walk), а когда просматриваются сначала потомки, а потом предки, то обход называется поступорядоченным обходом или обходом в обратном порядке (post-order walk). Существует также симметричный обход, при котором посещается сначала левое поддерево, затем узел, затем — правое поддерево, и обход в ширину, при котором узлы посещаются уровень за уровнем (N-й уровень дерева — множество узлов с высотой N). Каждый уровень обходится слева направо.

wikipedia

По умолчанию используется, обход в ширину.

массив

В результате из подобного массива получается такое меню.

древовидное меню битрикс

----- 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 -----

Вложения:
ФайлОписаниеРазмер файла:
Скачать этот файл (untitled.zip)untitled.zip 1 Кб