Меню из разделов инфоблока
Пусть у нас на сайте уже есть меню, которое содержит пункты: Каталог, Доставка, Оплата, Контакты. Для показа меню используется компонент bitrix:menu
, который в визуальном редакторе расположен по пути Служебные -> Навигация -> Меню
. А сами пункты меню сохраняются в файле .main.menu.php
, в корне сервера. Нам нужно, чтобы вместо пункта «Каталог» выводились названия корневых разделов каталога: Обувь, Одежда, Сумки.
<?
$aMenuLinks = array(
array(
"Каталог",
"/catalog/",
array(),
array(),
""
),
array(
"Доставка",
"/delivery/",
array(),
array(),
""
),
array(
"Оплата",
"/payment/",
array(),
array(),
""
),
array(
"Контакты",
"/contacts/",
array(),
array(),
""
)
);
Для решения этой задачи существует компонент «Пункты меню», который дополняет уже созданное меню названиями разделов инфоблоков. В визуальном редакторе компонент расположен по пути: Служебные -> Навигация -> Пункты меню
. Вызов этого компонета происходит в файле .main.menu_ext.php
.
Система Bitrix Framework позволяет создавать меню динамического типа. Т.е. массив данных таких меню генерируется автоматически на основании некоторых данных, получаемых с помощью программного кода. Данный код должен храниться в папке соответствующего раздела сайта в файле с именем .type.menu_ext.php
. Основная задача подобных файлов — это манипуляция массивом $aMenuLinks
.
Чтобы файл .main.menu_ext.php
мог изменять массив $aMenuLinks
, надо в настройках компонента «Меню» отметить checkbox, подключать файлы с именами вида .тип.menu_ext.php
:
Теперь создадим такой файл и разместим в нем код:
<?
/*
* файл .main.menu_ext.php в корне сервера
*/
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
global $APPLICATION;
$aMenuLinksExt = array();
if (CModule::IncludeModule('iblock')) {
$arFilter = array(
"CODE" => "catalog",
"SITE_ID" => SITE_ID,
);
// возвращает список информационных блоков по фильтру arFilter отсортированный в порядке arOrder
$dbIBlock = CIBlock::GetList(array('SORT' => 'ASC', 'ID' => 'ASC'), $arFilter);
$dbIBlock = new CIBlockResult($dbIBlock);
if ($arIBlock = $dbIBlock->GetNext()) {
// для сбоса кеша при изменении инфоблока
if (defined("BX_COMP_MANAGED_CACHE")) {
$GLOBALS["CACHE_MANAGER"]->RegisterTag("iblock_id_" . $arIBlock["ID"]);
}
if ($arIBlock["ACTIVE"] == "Y") {
$aMenuLinksExt = $APPLICATION->IncludeComponent(
"bitrix:menu.sections",
"",
array(
"IS_SEF" => "Y",
"SEF_BASE_URL" => "",
"SECTION_PAGE_URL" => $arIBlock['SECTION_PAGE_URL'],
"DETAIL_PAGE_URL" => $arIBlock['DETAIL_PAGE_URL'],
"IBLOCK_TYPE" => $arIBlock['IBLOCK_TYPE_ID'],
"IBLOCK_ID" => $arIBlock['ID'],
"DEPTH_LEVEL" => "1",
"CACHE_TYPE" => "N",
),
false,
array('HIDE_ICONS' => 'Y')
);
}
}
// для сброса кеша при добавлении нового инфоблока
if (defined("BX_COMP_MANAGED_CACHE")) {
$GLOBALS["CACHE_MANAGER"]->RegisterTag("iblock_id_new");
}
}
$aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks);
CIBlockResult
— вспомогательный класс для работы с объектами результатов выборок, наследуется от класса CDBResult
и содержит все его параметры и методы. Объекты данного класса возвращают методы CIBlockElement::GetList()
, CIBlockElement::GetByID()
и функции GetIBlockElementList()
, GetIBlockElementListEx
. Методы класса:
GetNext()
возвращает из выборки список полей элемента, с замененными ссылками в поляхDETAIL_PAGE_URL
иLIST_PAGE_URL
.GetNextElement()
возвращает объект_CIBElement
элемента из выборки.SetUrlTemplates()
устанавливает шаблоны путей для элементов.SetSectionContext()
метод устанавливает поля раздела в качестве родителя элемента для подстановки в шаблоны путей.
CDBResult CIBlock::GetList(
array arOrder = array("SORT"=>"ASC"),
array arFilter = array(),
bool bIncCnt = false
);
Осталось только удалить пункт меню «Каталог» из файла .main.menu.php
:
<?
$aMenuLinks = array(
array(
"Доставка",
"/delivery/",
array(),
array(),
""
),
array(
"Оплата",
"/payment/",
array(),
array(),
""
),
array(
"Контакты",
"/contacts/",
array(),
array(),
""
)
);
Если кроме корневых разделов каталога нам нужно еще выводить и подразделы, в файле .main.menu_ext.php
изменяем "DEPTH_LEVEL"=>"1"
на "DEPTH_LEVEL"=>"2"
и вносим изменения в шаблон компонента:
<?
/*
* Файл template.php
*/
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
?>
<?php if (!empty($arResult)): ?>
<?php $previousLevel = 0; ?>
<ul>
<?php foreach ($arResult as $arItem): ?>
<?php if ($arItem["DEPTH_LEVEL"] == $previousLevel): ?>
</li>
<?php endif; ?>
<?php if ($arItem["DEPTH_LEVEL"] > $previousLevel): /* открыть вложенный список */ ?>
<?php if ($previousLevel > 0): ?>
<ul>
<?php endif; ?>
<?php elseif ($arItem["DEPTH_LEVEL"] < $previousLevel): /* закрыть вложенный список */ ?>
</li>
</ul>
</li>
<?php endif; ?>
<?php if ($arItem["SELECTED"]): /* элемент списка <li> */ ?>
<li class="active">
<?php else: ?>
<li>
<?php endif; ?>
<a href="<?= $arItem["LINK"]; ?>"><?= $arItem["TEXT"]; ?></a>
<?php $previousLevel = $arItem["DEPTH_LEVEL"]; ?>
<?php endforeach; ?>
</li>
</ul>
<?php endif; ?>
Если нужен трехуровневый список, в файле .main.menu_ext.php
изменяем "DEPTH_LEVEL"=>"2"
на "DEPTH_LEVEL"=>"3"
и вносим изменения в шаблон компонента:
<?
/*
* Файл template.php
*/
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
?>
<?php if (!empty($arResult)): ?>
<ul>
<?php $previousLevel = 0; ?>
<?php foreach ($arResult as $arItem): ?>
<?php if ($previousLevel && $arItem["DEPTH_LEVEL"] < $previousLevel): ?>
<?= str_repeat("</ul></li>", ($previousLevel - $arItem["DEPTH_LEVEL"])); ?>
<?php endif; ?>
<?php if ($arItem["IS_PARENT"]): /* если есть дочерние элементы */ ?>
<?php if ($arItem["DEPTH_LEVEL"] == 1): /* корневой элемент */ ?>
<li class="root parent<?php if ($arItem["SELECTED"]): ?> active<?php endif; ?>">
<a href="<?= $arItem["LINK"]; ?>"><?= $arItem["TEXT"]; ?></a>
<ul>
<?php else: /* элемент второго, третьего уровня */ ?>
<li class="parent<?php if ($arItem["SELECTED"]): ?> active<?php endif; ?>">
<a href="<?= $arItem["LINK"]; ?>"><?= $arItem["TEXT"]; ?></a>
<ul>
<?php endif; ?>
<?php else: /* если нет дочерних элементов */ ?>
<?php if ($arItem["DEPTH_LEVEL"] == 1): /* корневой элемент */ ?>
<li class="root<?php if ($arItem["SELECTED"]): ?> active<?php endif; ?>">
<a href="<?= $arItem["LINK"]; ?>"><?= $arItem["TEXT"]; ?></a>
</li>
<?php else: /* элемент второго, третьего уровня */ ?>
<li<?php if ($arItem["SELECTED"]): ?> class="active"<?php endif; ?>>
<a href="<?= $arItem["LINK"]; ?>"><?= $arItem["TEXT"]; ?></a>
</li>
<?php endif; ?>
<?php endif; ?>
<?php $previousLevel = $arItem["DEPTH_LEVEL"]; ?>
<?php endforeach; ?>
<?php if ($previousLevel > 1): ?>
<?= str_repeat("</ul></li>", ($previousLevel-1)); ?>
<?php endif; ?>
</ul>
<?php endif; ?>