В принципе это стандартная возможность системы управления битрикс, но почему-то часто спрашивают как это сделать. Возможно в документации данный вопрос освещен не достаточно понятно. Постараюсь рассказать по простому, со скринами.
Добавляем разделы в инфоблок:
Предположим что нам нужно создать меню из подкатегорий новостей. У нас уже есть готовый инфоблок для новостей и он выведен на сайт. В общем новости работают. И наступил момент, что новостей стало достаточно много и пора их разбить на несколько категорий: "Спорт", "Финансы" и.т.д.
Для начала создаем эти разделы:
Теперь задача создать пункты выпадающего меню, которое автоматически будет брать разделы в качестве своих пунктов. Для этого нужно создать необходимый тип меню в Управлении структурой. В моем случае я создаю тип меню "Меню подраздела"
Создаем в нужном каталоге сайта этот тип меню и рядом с ним создаем такой же файл с приставкой _ext.php.
В моем примере я создаю блог на основе компонента новостей, потому каталог и соответствующий инфоблок называются blog
Настройка ext меню в битрикс
В меню сайта необходимо подключить соответствующее меню в пункте "Тип меню для остальных уровней:" и установить чекбокс для "Подключать файлы с именами вида .тип_меню.menu_ext.php:"
В наше ..._ext.php меню вносим вот такие данные:
<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
global $APPLICATION;
$aMenuLinksExt=$APPLICATION->IncludeComponent("bitrix:menu.sections", "", array(
"IS_SEF" => "Y",
"SEF_BASE_URL" => "/blog/",
"SECTION_PAGE_URL" => "#SECTION_ID#/",
"DETAIL_PAGE_URL" => "#SECTION_ID#/#ELEMENT_ID#.html",
"IBLOCK_TYPE" => "company",
"IBLOCK_ID" => "5",
"DEPTH_LEVEL" => "3",
"CACHE_TYPE" => "A",
"CACHE_TIME" => "36000000"
),
false
);
$aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks);
?>
Где:
- "SEF_BASE_URL" => "/blog/", - каталог инфоблока на сайте
- "SECTION_PAGE_URL" => "#SECTION_ID#/", - подставляем ID раздела
- "DETAIL_PAGE_URL" => "#SECTION_ID#/#ELEMENT_ID#.html", - полный путь к элементу инфоблока
- "IBLOCK_TYPE" => "company", - ID типа инфоблока из которого выводим
- "IBLOCK_ID" => "5", ID инфоблока из которого выводим
- "DEPTH_LEVEL" => "4", уровень вложенности, этой цифрой можно выводить подразделы разделов если иерархия многоуровневая
В настройках компонента инфоблока также прописываем аналогичный путь к элементам и разделам инфоблока
В итоге все вновь создаваемые разделы инфоблока будут автоматически попадать в выпадающее меню (в моем случае, вы можете проделать эти манипуляции для любого типа меню)
Надеюсь объяснил наглядно и понятно, если остались вопросы или есть чем дополнить данную записку, прошу писать в комментариях. Всем успехов.
Элементы инфоблока в меню
Таким же образом можно сделать и меню из элементов инфоблока или вообще чего угодно. Просто, в файле меню с типом _ext наполняете массив $aMenuLinksExt нужными данными
Что бы получить элементы и их ссылки достаточно воспользоваться методом CIBlockElement::GetList
Быстрый пример:
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
global $APPLICATION;
if(CModule::IncludeModule("iblock")) {
$res = CIBlockElement::GetList(
false,
array(
"IBLOCK_ID"=> 5, // ID нужного инфоблока
"ACTIVE"=>"Y"
),
false,
false,
array( // Нужны только названиеи ссылка
"NAME"
"DETAIL_PAGE_URL"
),
);
while($arFields = $res->Fetch()){
$aMenuLinksExt[] = Array(
$arFields['NAME'],
$arFields['DETAIL_PAGE_URL'],
Array(),
Array(),
""
);
}
}
$aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks);
Цитата |
---|
Alex написал: Месяц знакомлюсь с битриксом. Сделал вывод: если есть возможность, то лучше не использовать эту "технологию". С меню мучаюсь уже неделю. Не могу сделать меню из разделов и элементов раздела. Если бы я использовал реакт или даже нативный php, то сделал бы это меню за несколько часов. Здесь же я мучаюсь. Такой тупей шей реализации еще не встречал! |
Да, для такого лучше использовать catalog.section.list - элементы можно добавить в массив, для вывода меню, через result_modifier.php
Если есть время, совсем хорошо сделать свой компонент, что бы лишнее не тянуть.
Проверять какой блок находится в зоне видимости и по id пункта меню добавлять ему нужный class
То есть, грубо говоря, если блок с id="block1" сейчас по offset 0 от верха страницы, то добавить class="selected" для пункта меню с id="link_to_block1"
Код |
---|
<? if(!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true)die(); global $APPLICATION; if(CModule::IncludeModule('iblock')) { $IBLOCK_ID = 7; // ID инфоблока из которого берем элементы $arOrder = Array('NAME'=>'ASC'); // Выбрать сортировку $arSelect = Array('ID', 'NAME', 'IBLOCK_ID', 'DETAIL_PAGE_URL'); $arFilter = Array('IBLOCK_ID'=>$IBLOCK_ID, 'ACTIVE'=>'Y', 'PROPERTY_razdel'=> $_REQUEST['SECTION_ID']); $res = CIBlockElement::GetList($arOrder, $arFilter, false, false, $arSelect); while($ob = $res->GetNextElement()) { $arFields = $ob->GetFields(); $aMenuLinksExt[] = Array( $arFields['NAME'], $arFields['DETAIL_PAGE_URL'], Array(), Array(), '' ); } } $aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks); ?> |
Если честно, впервые столкнулся с Битрикс и .php
Михаил, не могли бы вы объяснить разницу между Вашим решением и вышеприведённым? Спасибо
* При внедрении Вашего решения неоднократно чистил кэш как в настройках Битрикс, так и через админпанель
Попробовал поменять код файла .тип_меню.menu_ext.php:
Код |
---|
<? if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();global $APPLICATION; if (CModule::IncludeModule('iblock')) { $IBLOCK_ID = 11; // ID инфоблока из которого берем элементы $arOrder = Array('NAME' => 'ASC'); // Выбрать сортировку $arSelect = Array('ID', 'NAME', 'IBLOCK_ID', 'DETAIL_PAGE_URL', 'PREVIEW_PICTURE'); // Включить PREVIEW_PICTURE в выборку $arFilter = Array('IBLOCK_ID' => $IBLOCK_ID, 'ACTIVE' => 'Y', 'PROPERTY_razdel' => $_REQUEST['SECTION_ID']); $res = CIBlockElement::GetList($arOrder, $arFilter, false, false, $arSelect); while ($ob = $res->GetNextElement()) { $arFields = $ob->GetFields(); $imageSrc = !empty($arFields['PREVIEW_PICTURE']) ? CFile::GetPath($arFields['PREVIEW_PICTURE']) : ''; // Получаем путь к изображению $aMenuLinksExt[] = Array( $arFields['NAME'], $arFields['DETAIL_PAGE_URL'], Array(), Array(), '', 'PARAMS' => array( 'IMG_SRC' => $imageSrc, // Передаем путь к изображению в параметрах ), ); } } $aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks); ?> |
Код шаблона меню:
Код |
---|
<? if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); ?> <? if (!empty($arResult)): ?> <ul id="horizontal-multilevel-menu"> <? $previousLevel = 0; foreach ($arResult as $arItem): $imageSrc = !empty($arItem['PREVIEW_PICTURE']) ? CFile::GetPath($arItem['PREVIEW_PICTURE']) : ''; // Получаем путь к изображению if ($previousLevel && $arItem["DEPTH_LEVEL"] < $previousLevel) { echo str_repeat("</ul></li>", ($previousLevel - $arItem["DEPTH_LEVEL"])); } if ($arItem["IS_PARENT"]) { if ($arItem["DEPTH_LEVEL"] == 1) { ?> <li> <?php if (!empty($imageSrc)): ?> <img src="<?= $imageSrc ?>" alt="<?= $arItem["TEXT"] ?>" class="menu-item-image"> <?php endif; ?> <a href="<?= $arItem["LINK"] ?>" class="<?= $arItem["SELECTED"] ? 'root-item-selected' : 'root-item' ?>"> <?= $arItem["TEXT"] ?> </a> <ul> <?php } else { ?> <li<?= $arItem["SELECTED"] ? ' class="item-selected"' : '' ?>> <a href="<?= $arItem["LINK"] ?>" class="parent"><?= $arItem["TEXT"] ?></a> <ul> <?php } } else { if ($arItem["PERMISSION"] > "D") { if ($arItem["DEPTH_LEVEL"] == 1) { ?> <li> <?php if (!empty($imageSrc)): ?> <img src="<?= $imageSrc ?>" alt="<?= $arItem["TEXT"] ?>" class="menu-item-image"> <?php endif; ?> <a href="<?= $arItem["LINK"] ?>" class="<?= $arItem["SELECTED"] ? 'root-item-selected' : 'root-item' ?>"> <?= $arItem["TEXT"] ?> </a> </li> <?php } else { ?> <li<?= $arItem["SELECTED"] ? ' class="item-selected"' : '' ?>> <a href="<?= $arItem["LINK"] ?>"><?= $arItem["TEXT"] ?></a> </li> <?php } } else { if ($arItem["DEPTH_LEVEL"] == 1) { ?> <li> <a href="" class="<?= $arItem["SELECTED"] ? 'root-item-selected' : 'root-item' ?>" title="<?= GetMessage("MENU_ITEM_ACCESS_DENIED") ?>"> <?= $arItem["TEXT"] ?> </a> </li> <?php } else { ?> <li> <a href="" class="denied" title="<?= GetMessage("MENU_ITEM_ACCESS_DENIED") ?>"><?= $arItem["TEXT"] ?></a> </li> <?php } } } $previousLevel = $arItem["DEPTH_LEVEL"]; endforeach; if ($previousLevel > 1) { echo str_repeat("</ul></li>", ($previousLevel - 1)); } ?> </ul> <div class="menu-clear-left"></div> <? endif ?> В итоге ничего не меняется. Визуально все остается таким же, код работает. Если просто добавить [/COLOR][/FONT][/COLOR][CODE]$arFields['PREVIEW_PICTURE'], $arFields ['DETAIL_PICTURE'], |
в массив $aMenuLinksExt, то меню ломается, вылезает ошибка.
Подскажите, что я делаю не так? Опыт битрикс и php нулевой, извините за тупость
А дополучить внутри них элементы уже дело техники - там не сложно.
как сделать для нескольких инфоблоков?
Цитата |
---|
Гость написал: Добрый день, как сделать для нескольких инфоблоков? |
Нужно будет кастомизировать компонент bitrix:menu.sections
Но лучше написать свой, который параметрами будет принимать нужны инфоблоки и собирать массив arResult в шаблон