Многоуровневое меню - свои пункты и вывод из инфоблока
Выводим многоуровневое меню, собираем его пункты из инфоблока и оформляем активный пункт в шаблоне.
Решение
Смотрим, как устроен файл меню:
// /catalog/.left.menu.php - файл меню типа left в разделе /catalog/$aMenuLinks = [ ['Одежда', '/catalog/odezhda/', [], [], ''], ['Обувь', '/catalog/obuv/', [], ['CLASS' => 'is-new'], ''],];Пункт - это массив из пяти элементов: название, адрес, дополнительные адреса для подсветки, произвольные параметры и условие показа. Пятый элемент - строка кода на PHP, и пустая строка означает «показывать всегда».
Выводим меню с нужной глубиной:
$APPLICATION->IncludeComponent('bitrix:menu', 'tree', [ 'ROOT_MENU_TYPE' => 'left', 'MAX_LEVEL' => 3, // глубина задаётся здесь, а не в файле 'CHILD_MENU_TYPE' => 'left', 'USE_EXT' => 'Y', // разрешает подключаемые файлы меню 'DELAY' => 'N',]);Уровни собираются из файлов меню вложенных разделов. Второй уровень появится только там, где у раздела есть свой файл меню того же типа, и параметр глубины без этих файлов ничего не даёт.
Собираем пункты из инфоблока:
// /catalog/.left.menu_ext.php - подключаемый файл, дополняет основной$res = CIBlockSection::GetList(['SORT' => 'ASC'], ['IBLOCK_ID' => 5, 'ACTIVE' => 'Y', 'SECTION_ID' => false], false, ['ID', 'NAME', 'SECTION_PAGE_URL']);while ($section = $res->GetNext()) { $aMenuLinksExt[] = [$section['NAME'], $section['SECTION_PAGE_URL'], [], [], ''];}Подключаемый файл работает только при разрешающем параметре компонента. Страниц для таких пунктов создавать не нужно: меню не проверяет, существует ли адрес, и рисует пункт в любом случае.
Выборка в файле меню выполняется на каждой странице, где это меню выводится. Тяжёлый запрос там обходится дороже, чем кажется, поэтому кэширование компонента на таком меню оставляют включённым, а сбрасывают его по событию изменения разделов.
Оформляем активный пункт в шаблоне:
// шаблон компонента: признак активности приходит вместе с пунктомforeach ($arResult as $item) { $class = $item['SELECTED'] ? 'menu-item is-active' : 'menu-item'; printf('<a href="%s" class="%s">%s</a>', $item['LINK'], $class, $item['TEXT']);}Активность определяется совпадением адреса пункта с адресом страницы. Раздел, адрес которого не совпадает с адресом текущей страницы буква в букву, подсвечиваться не будет: для таких случаев есть третий элемент массива.
Условие показа в пятом элементе - обычное выражение на PHP. Туда кладут проверку группы пользователя или прав на раздел, и пункт исчезает у тех, кому он не предназначен. Пустая строка означает, что пункт видят все, включая неавторизованных посетителей.
Кэш меню живёт отдельно от кэша страницы. Пункты, собранные из инфоблока, обновляются после сброса кэша компонента, а не сразу после правки данных. На время настройки кэширование меню отключают, иначе каждая проверка требует ручного сброса.
Типичные проблемы
Второй уровень меню не появляется.
У вложенных разделов нет своих файлов меню. Параметр глубины задаёт предел, но пункты берутся из файлов, а не создаются сами.
Пункты из инфоблока не выводятся.
Не включён параметр подключаемых файлов меню. Без него дополняющий файл не читается вовсе.
Активный пункт не подсвечивается.
Адрес пункта не совпадает с адресом страницы. Дополнительные адреса для подсветки задают третьим элементом массива пункта.
Правка меню не видна на сайте.
Компонент отдаёт результат из кэша. Кэш меню сбрасывается отдельно от кэша страницы.
Пункт показывается всем, хотя нужен только своим.
Пустое условие показа в пятом элементе массива. Туда кладут выражение с проверкой прав или группы.
Частые вопросы
Можно ли сделать меню без создания страниц?
Да, пункты меню не связаны со структурой файлов. Адрес в пункте может вести куда угодно, в том числе на страницу, которую рисует компонент каталога.
Как вывести только подпункты одного раздела?
Компонентом с типом меню этого раздела и ограничением по корню. Собственный вывод строят выборкой по разделам инфоблока, если пункты приходят оттуда.
Как добавить картинку в пункт меню?
Через дополнительные параметры пункта: четвёртый элемент массива приходит в шаблон целиком. Разметку рисует шаблон компонента.
Чем отличаются типы меню?
Только именем: тип определяет, какой файл читать в разделе. Верхнее и левое меню - два разных типа и два разных файла в одном и том же разделе.
Смежное
- Меню и хлебные крошки - оглавление подтемы
- Кэш меню: разрастание каталога, тяжёлые запросы, настройка - скорость и объём кэша меню
- Меню показывает не то: разбор причин - когда меню пустое или чужое
- Хлебные крошки: правка цепочки и свои элементы - вторая часть навигации
- Меню и навигация - устройство меню целиком
- Компоненты 2.0 - параметры и шаблоны
- Вывод разделов: дерево, подразделы, адреса - разделы как источник пунктов меню
- Стили и скрипты в шаблоне: подключение, порядок, кэш - стили меню в шаблоне сайта
- Фильтрация разделов по свойству элементов: список без пустых - меню только с непустыми разделами
- Меню изнутри: файлы, типы, сборка пунктов, кэш - устройство файлов и сборки пунктов