Древовидное меню из компонента «Структура разделов»

Мне никогда не нравилось использовать в качестве меню стандартный компонент bitrix:catalog.section.list, который «Структура разделов», хотя при разработке любого каталога или интернет-магазина, он просто незаменим. А когда дело доходит до многоуровневых каталогов, мозг потихоньку начинает взрываться от отсутствия древовидного массива.

Дано:

  1. Битрикс с каталогом и неограниченной вложенностью разделов;
  2. Необходимость организовать настоящую навигацию по каталогу с автогенерацией и активным пунктом;
  3. Желание получить удобный шаблон меню.

Решение.

Итак, в первую очередь — создание типа меню для разделов каталога, для этого переходим в раздел Настройки > Настройки продукта > Настройки модулей > Управление структурой административной части сайта и создаем новый тип меню. Для примера: тип — catalog, название — «Меню каталога»

Следующим шагом встроим в шаблон сайта в нужном месте bitrix:menu. Далее в режиме правки выбираем «копировать шаблон компонента», называем новый шаблон «sections», ставим нужный уровень вложенности меню.
Должно получиться что-то типа того:

<? $APPLICATION->IncludeComponent(
 "bitrix:menu",
 "sections",
 array(
 "ALLOW_MULTI_SELECT" => "Y",
 "CHILD_MENU_TYPE" => "left",
 "COMPONENT_TEMPLATE" => "tree",
 "DELAY" => "N",
 "MAX_LEVEL" => "4",
 "MENU_CACHE_GET_VARS" => array(
 ),
 "MENU_CACHE_TIME" => "3600",
 "MENU_CACHE_TYPE" => "N",
 "MENU_CACHE_USE_GROUPS" => "Y",
 "ROOT_MENU_TYPE" => "catalog",
 "USE_EXT" => "N"
 ),
 false
);?>

Затем, в корне сайта или в нужном разделе сайта создаем файл .catalog.menu.php, который будет генерировать наше меню. В него вставляем:

<?php if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
global $APPLICATION;

$aMenuLinksExt = $APPLICATION->IncludeComponent(
 "bitrix:menu.sections",
 "",
 array(
 "IS_SEF" => "Y",
 "ID" => $_REQUEST["ID"],
 "IBLOCK_TYPE" => "catalog",
 "IBLOCK_ID" => 2,//Укажите реальный ID инфоблока каталога
 "SECTION_URL" => "",
 "DEPTH_LEVEL" => "4",//Количество уровней меню
 "CACHE_TYPE" => "Y",//Настройки кеширования
 "CACHE_TIME" => "3600",
 //Настройки ЧПУ каталога
 "SEF_BASE_URL" => "/catalog/",
 "SECTION_PAGE_URL" => "#SECTION_CODE_PATH#/",
 "DETAIL_PAGE_URL" => "#SECTION_CODE_PATH#/#ELEMENT_CODE#/"
 ),
 false
);

$aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks);

В шаблоне меню, рядом с template.php, создаем файл result_modifier.php и наполняем его:

<?php if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();

$menuList = array();
$lev = 0;
$lastInd = 0;
$parents = array();
foreach ($arResult as $arItem) {
 $lev = $arItem['DEPTH_LEVEL'];
 
 if ($arItem['IS_PARENT']) {
 $arItem['CHILDREN'] = array();
 }
 
 if ($lev == 1) {
 $menuList[] = $arItem;
 $lastInd = count($menuList)-1;
 $parents[$lev] = &$menuList[$lastInd];
 } else {
 $parents[$lev-1]['CHILDREN'][] = $arItem;
 $lastInd = count($parents[$lev-1]['CHILDREN'])-1;
 $parents[$lev] = &$parents[$lev-1]['CHILDREN'][$lastInd];
 }
}
$arResult = $menuList;

 

В результате мы получаем красивый древовидный массив и очень простой код шаблона:

<? if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
if (!empty($arResult)):?>
<?function getItems($a) {
foreach($a as $arItem):?>
 <li<?=$arItem["SELECTED"]?' class="active"':''/*выделяем активный пункт (текущий раздел)*/?> <a href="<?=$arItem["LINK"]?>"><?=$arItem["TEXT"]?></a>
 <?if($arItem["IS_PARENT"]):?>
 <ul>
 <?getItems($arItem["CHILDREN"])?>
 </ul>
 <?endif?>
 </li>
<?endforeach;
}
getItems($arResult);?>
<?endif?>

Здесь вариант для наглядности, однако, с точки зрения Bitrix Framework, правильнее будет вынести саму функцию в файл /bitrix/php_interface/init.php (если его нет, то создайте, если есть, то просто в конце допишите указанный ниже код), а её вызов оставить в шаблоне.
init.php:

function getItems($a) {
foreach($a as $arItem):?>
 <li<?=$arItem["SELECTED"]?' class="active"':''?> <a href="<?=$arItem["LINK"]?>"><?=$arItem["TEXT"]?></a>
 <?if($arItem["IS_PARENT"]):?>
 <ul>
 <?getItems($arItem["CHILDREN"])?>
 </ul>
 <?endif?>
 </li>
<?endforeach;
}

template.php:

<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
getItems($arResult);

Встречал такой интересный вопрос: почему в Битриксе не додумались сделать древовидный массив меню?
Суть вот в чем: во-первых, мы не знаем сколько будет уровней в массиве, поэтому нам пришлось применять рекурсию. Для программиста это легко и просто, но представьте себя на месте верстальщика, который виртуозно расставляет теги, прописывает стили и прошел курс верстки шаблонов под Битрикс. Он не имеет понятия чем отличается цикл от рекурсии, но знает в какой папке должен находиться HTML-код шаблона. Если так и не поняли, то прочтите статью заново и всё станет на свои места 🙂

Древовидное меню из компонента «Структура разделов»: 1 комментарий

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.