Перейти к содержимому

Меню и хлебные крошки в 1С-Битрикс

Меню в 1С-Битрикс устроено непривычно: пункты хранятся не в базе, а в файлах внутри папок разделов, и наследуются вверх по структуре сайта. Разберём эту механику, динамические меню из инфоблоков и настройку хлебных крошек.

Как это работает

Тип меню - это просто имя набора пунктов. Идентификатор латиницей: top, left, bottom. Задаётся в настройках модуля управления структурой и никак не привязан к расположению на странице - где выводить, решает шаблон.

На каждый тип приходится два файла в папке раздела. Файл .<тип>.menu.php содержит статическое меню - PHP-массив $aMenuLinks, который правят вручную. Файл .<тип>.menu_ext.php строит пункты кодом, например из разделов инфоблока. Они могут существовать одновременно.

Пункт меню - это массив из пяти элементов: название, ссылка, массив дополнительных ссылок для подсветки активности, массив дополнительных параметров и условие показа в виде PHP-выражения, которое должно вернуть истину.

Наследование идёт вверх и останавливается на первом найденном файле. Система ищет файл меню в текущем разделе, затем в родительском, затем в корне - и берёт первый найденный независимо от его содержимого. Отсюда неочевидное следствие: пустой файл меню в подразделе переопределяет родительское меню как пустое, и меню просто исчезает. Ещё одна тонкость: статическое меню заменяется только статическим, динамическое - только динамическим.

Компонент bitrix:menu читает файлы и отдаёт шаблону массив пунктов. У каждого пункта есть TEXT, LINK, SELECTED (пользователь находится на этой странице), ITEM_TYPE (раздел, страница или страница с параметрами), PARAMS и PERMISSION. Стандартные шаблоны поддерживают до четырёх уровней вложенности.

Навигационная цепочка выводится компонентом bitrix:breadcrumb, который ставят в шаблон сайта, чтобы он был на всех страницах. Текст пункта берётся из заголовка раздела, а для элементов инфоблока - из названия. Произвольный пункт добавляют из кода.

Примеры

1. Статическое меню

<?
$aMenuLinks = Array(
Array(
"Новости", "news/",
Array(), // дополнительные ссылки для подсветки
Array(), // дополнительные параметры
"CSite::InDir('/index.php')" // условие показа
),
Array(
"Профиль", "profile.php",
Array(), Array(),
"\$GLOBALS['USER']->IsAuthorized()"
),
);
?>

Пункт «Профиль» увидят только авторизованные пользователи. Условие - это строка с PHP-выражением, которую вычисляет компонент меню; кроме проверки авторизации часто используют CSite::InDir() для конкретного раздела и CSite::InGroup() для групп пользователей.

2. Динамическое меню из разделов инфоблока

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
global $APPLICATION;
$aMenuLinksExt = $APPLICATION->IncludeComponent(
"bitrix:menu.sections", "",
Array(
"ID" => (int)($_REQUEST["ELEMENT_ID"] ?? 0), // приводим ввод к числу
"IBLOCK_TYPE" => "books",
"IBLOCK_ID" => "30",
"SECTION_URL" => "/e-store/books/index.php?SECTION_ID=#ID#",
"CACHE_TIME" => "3600",
)
);
$aMenuLinks = array_merge($aMenuLinks, $aMenuLinksExt);
?>

Три обязательных элемента такого файла: защита от прямого вызова в начале, объявление global $APPLICATION и слияние результата со статическими пунктами в конце. И четвёртое, не в файле: в параметрах компонента bitrix:menu должна быть включена опция подключения файлов menu_ext.php - без неё динамические пункты просто не появятся.

Шаблон адреса раздела берут из настроек инфоблока: без человекопонятных адресов это вид /catalog/index.php?SECTION_ID=#ID#, с ними - /catalog/#SECTION_CODE#/.

3. Свой шаблон меню

<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); ?>
<ul class="nav">
<?php foreach ($arResult as $arItem): ?>
<li class="<?= $arItem['SELECTED'] ? 'active' : '' ?>">
<a href="<?= $arItem['LINK'] ?>"><?= $arItem['TEXT'] ?></a>
</li>
<?php endforeach; ?>
</ul>

Шаблон копируют в шаблон сайта, в папку /local/templates/<шаблон>/components/bitrix/menu/<имя>/, и правят копию. Разметку можно менять полностью; активный пункт определяется по признаку SELECTED.

В многоуровневых меню ссылки на подразделы ведите на папку, а не на index.php внутри неё - иначе подсветка активного пункта будет работать некорректно.

4. Хлебные крошки

<? $APPLICATION->AddChainItem("Форум «Отзывы»", "/ru/forum/list.php?FID=3"); ?>

Пункт добавляется в конец цепочки. Вызывать можно из кода страницы или шаблона. Сам компонент bitrix:breadcrumb ставят в шаблон сайта - тогда цепочка появляется на всех страницах разом.

Справочник API

ЭлементНазначениеОсобенности
.<тип>.menu.phpстатическое меню разделамассив $aMenuLinks
.<тип>.menu_ext.phpдинамическое менюнужен array_merge и включённая опция подключения в компоненте
пункт $aMenuLinksпять элементовназвание, ссылка, доп. ссылки, доп. параметры, условие показа
bitrix:menuвывод менюпараметры включают тип меню, уровни вложенности, кеш
USE_EXTподключение динамических файловбез него menu_ext.php игнорируется
$arItem['SELECTED']признак активного пункта
$arItem['ITEM_TYPE']тип пунктараздел, страница, страница с параметрами
$arItem['PERMISSION']уровень доступатолько для меню сайта
bitrix:menu.sectionsпункты из разделов инфоблокавызывается внутри menu_ext.php
bitrix:breadcrumbнавигационная цепочкаставится в шаблон сайта
AddChainItem()добавление пункта в цепочкудобавляет в конец

Частые ошибки

Меню исчезло в подразделе. Симптом: в одной ветке сайта меню пустое. Причина - файл меню в этом разделе, пусть даже пустой: поиск останавливается на нём и родительское меню не подхватывается. Файл нужно удалить или переименовать.

Динамическое меню не работает. Либо нет файла menu_ext.php, либо в параметрах компонента bitrix:menu не включено подключение таких файлов.

Меню не заменилось при наследовании. Статическое меню заменяется только статическим, динамическое - только динамическим. Если ожидали, что динамика перекроет статику, - не перекроет.

Создали страницу с опцией «Добавить пункт меню» и потеряли меню раздела. Опция незаметно создаёт собственный файл меню в подразделе, а он скрывает унаследованное меню родителя во всей ветке.

Изменения не видны. Меню кешируется - очистите кеш. Если конкретный пункт не появляется, проверьте условие показа и права доступа.

Кеш меню разросся до неприличных размеров. Он зависит от адреса страницы, поэтому на сайтах с большим числом страниц растёт быстро. Отключать его не нужно - вынесите тяжёлые запросы из шаблона в menu_ext.php и настройте зависимости кеша.

Частые вопросы

Почему меню в подразделе стало пустым?

Потому что поиск файла меню идёт вверх по разделам и останавливается на первом найденном - независимо от содержимого. Если в подразделе лежит пустой файл нужного типа, он и станет меню этой ветки, а родительское не подхватится. Решение простое: удалить или переименовать файл в подразделе.

Как построить меню из разделов каталога?

Через файл .тип.menu_ext.php: в нём вызывают компонент bitrix:menu.sections, получают массив пунктов и объединяют его со статическими через array_merge. Не забудьте включить в параметрах компонента bitrix:menu опцию подключения файлов menu_ext - это самая частая причина, по которой динамическое меню «не работает».

Где выводить хлебные крошки?

В шаблоне сайта, обычно сразу после шапки - тогда цепочка появится на всех страницах без правки каждой. Текст пунктов система берёт из заголовков разделов и названий элементов инфоблока, а произвольный пункт добавляется из кода методом AddChainItem().

Можно ли полностью изменить вёрстку меню?

Да. Скопируйте шаблон компонента в шаблон сайта и правьте копию: в цикле по результату доступны текст, ссылка, признак активности и тип пункта, а разметку списка можно заменить на любую свою. Правило то же, что и для остальных компонентов: файлы в папке /bitrix/ не трогаем.

Связанные темы

Первоисточники