Меню из разделов инфоблока с элементами

24.09.2013

В битриксе можно создавать меню из разделов инфоблока, для этого к компоненту menu подключается файл типа *.menu_ext.php, а в нем вызывается компонент menu.sections. Но нет возможности включать в меню элементы разделов, а это иногда бывает полезно. Так, кстати, сделано на этом сайте.

Для этого я сделал компонент menu.sections.elements, подключается он так же в файле *.menu_ext.php, коды я приведу ниже:

.parameters.php


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

if(!CModule::IncludeModule("iblock"))
	return;

$arTypesEx = CIBlockParameters::GetIBlockTypes(Array("all"=>" "));

$arIBlocks=Array();
$db_iblock = CIBlock::GetList(Array("SORT"=>"ASC"), Array("SITE_ID"=>$_REQUEST["site"], "TYPE" => ($arCurrentValues["IBLOCK_TYPE"]!="all"?$arCurrentValues["IBLOCK_TYPE"]:"")));
while($arRes = $db_iblock->Fetch())
	$arIBlocks[$arRes["ID"]] = $arRes["NAME"];

$arComponentParameters = array(
	"GROUPS" => array(
	),
	"PARAMETERS" => array(
		"IBLOCK_TYPE" => Array(
			"PARENT" => "BASE",
			"NAME"=>GetMessage("CP_BMS_IBLOCK_TYPE"),
			"TYPE"=>"LIST",
			"VALUES"=>$arTypesEx,
			"DEFAULT"=>"catalog",
			"ADDITIONAL_VALUES"=>"N",
			"REFRESH" => "Y",
		),
		"IBLOCK_ID" => Array(
			"PARENT" => "BASE",
			"NAME"=>GetMessage("CP_BMS_IBLOCK_ID"),
			"TYPE"=>"LIST",
			"VALUES"=>$arIBlocks,
			"DEFAULT"=>'1',
			"MULTIPLE"=>"N",
			"ADDITIONAL_VALUES"=>"N",
			"REFRESH" => "Y",
		),
		"DEPTH_LEVEL" => Array(
			"PARENT" => "DATA_SOURCE",
			"NAME" => GetMessage("CP_BMS_DEPTH_LEVEL"),
			"TYPE" => "STRING",
			"DEFAULT" => "1",
		),
		"CACHE_TIME"  =>  Array("DEFAULT"=>36000000),
	),
);

component.php


if (!function_exists('createMenuArray')){
    function createMenuArray(&$res,&$menuItems,$arParent,$depthLevel){
        foreach($arParent as $item){
            $isParent = ($item['IS_SECTION']&&isset($menuItems[$item['ID']]));
            $res[] = array(
                htmlspecialchars($item['~NAME']),
                $item['LINK'],
                array(), //массив доп ссылок
                array(
                    'FROM_IBLOCK' => true,
                    'IS_PARENT' => $isParent,
                    'DEPTH_LEVEL' => $depthLevel,
                ),
            );
            if ($isParent){
                createMenuArray($res,$menuItems,$menuItems[$item['ID']],$depthLevel+1);
            }
        }
    }
}
if(!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();

if(!isset($arParams['CACHE_TIME']))
	$arParams['CACHE_TIME'] = 36000000;

$arParams['IBLOCK_ID'] = intval($arParams['IBLOCK_ID']);

$arParams['DEPTH_LEVEL'] = intval($arParams['DEPTH_LEVEL']);
if($arParams['DEPTH_LEVEL']<=0)
	$arParams['DEPTH_LEVEL']=1;

if($this->StartResultCache()) {
    CModule::IncludeModule('iblock');
    $arSectionId = array();
    $arFilter = array(
            'IBLOCK_ID'=>$arParams['IBLOCK_ID'],
            'GLOBAL_ACTIVE'=>'Y',
            'ACTIVE'=>'Y',
            '<=DEPTH_LEVEL' => $arParams['DEPTH_LEVEL'],
    );
    $arOrder = array(
            'SORT'=>'ASC',
    );
    $rsSections = CIBlockSection::GetList($arOrder, $arFilter, false, array(
            'ID',
            'DEPTH_LEVEL',
            'NAME',
            'SECTION_PAGE_URL',
            'IBLOCK_SECTION_ID',
    ));
    $menuItems = array();
    while($arSection = $rsSections->GetNext()){
        $arSection['IS_SECTION'] = 1;
        $arSection['LINK'] = $arSection['SECTION_PAGE_URL'];
        if ($arSection['IBLOCK_SECTION_ID']){
            $menuItems[$arSection['IBLOCK_SECTION_ID']][] = $arSection;
        } else {
            $menuItems['ROOT'][] = $arSection;
        }
        $arSectionId[] = $arSection['ID'];
    }
    //Получим элементы
    $arSelect = Array('ID', 'NAME','DETAIL_PAGE_URL', 'IBLOCK_SECTION_ID');
    $arFilter = Array(
        'IBLOCK_ID' => $arParams['IBLOCK_ID'],
        'ACTIVE' => 'Y',
        array(
        'LOGIC' => 'OR',
            array('SECTION_ID' => $arSectionId),
            array('SECTION_ID' => false),
        ),
    );
    $arOrder = Array('SORT' => 'ASC');
    $res = CIBlockElement::GetList($arOrder, $arFilter, false, false, $arSelect);  
    while ($ob = $res->GetNextElement()){
        $arFields = $ob->GetFields();
        $arFields['IS_SECTION'] = 0;
        $arFields['LINK'] = $arFields['DETAIL_PAGE_URL'];
        if ($arFields['IBLOCK_SECTION_ID']){
            $menuItems[$arFields['IBLOCK_SECTION_ID']][] = $arFields;
        } else {
            $menuItems['ROOT'][] = $arFields;
        }
    }
    //Рекурсивно сформируем итоговый массив для меню
    $arResult = array();
    createMenuArray($arResult,$menuItems,$menuItems['ROOT'],1);
    $this->EndResultCache();
}
return $arResult;

.left.menu_ext.php (для примера)


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

global $APPLICATION;

$aMenuLinksExt=$APPLICATION->IncludeComponent(
	"max22:menu.sections.elements",
	 "", 
	 array(
		"IBLOCK_TYPE" => "content",
		"IBLOCK_ID" => "1",
		"DEPTH_LEVEL" => "5",
		"CACHE_TYPE" => "A",
		"CACHE_TIME" => "36000000"
	),
	false
);
$aMenuLinks = array_merge($aMenuLinksExt, $aMenuLinks);
?>

Не забываем размещать свои компоненты в своем пространстве имен, в примере это max22

Комментарии:

Lia

24.07.2014 19:26:48

Спасибо большое! Пригодилось =)

Кирилл

29.08.2014 18:05:30

Аналогично . Побольше бы таких статей . экономило бы время

Костя

16.09.2014 16:44:44

Круто, работает, 1000 благодарностей)

Bronskiy

12.01.2015 11:48:16

Спасибо большое. А можете шаблон компонента тоже выложить?

Максим

12.01.2015 14:13:02

Данный компонент не требует шаблона. Отображением занимается стандартный компонент bitrix:menu. Подойдет любой многоуровневый шаблон.

Bronskiy

12.01.2015 20:19:29

да, я уже применил. потом понял что глупость спросил) спасибо еще раз

Иван

14.01.2015 12:24:13

Скажите, а как ограничить количество элементов инфоблока в меню? Например, нужно выводить не более 5 элементов.

Максим

14.01.2015 19:59:45

Иван, в таком случае нужно получать элементы в цикле по найденым разделам, и ограничивать выборку 5-ю. Либо оставить как есть и уже после в цикле оставить по 5 элементов. Либо уже в шаблоне меню вывод ограничивать 5-ю элементами.

Варианты отличаются по типу создаваемой нагрузки на сервер, какой выбрать оптимальнее нужно смотреть по конкретной ситуации.

Иван

15.01.2015 11:59:50

Спасибо за совет. А можно как-то выводить не все подразделы и элементы инфоблока, а только содержимое одного (то есть его подразделы и элементы, не выводя его самого)?

Максим

15.01.2015 12:42:14

Иван, да, можно конечно. Модифицируйте запрос и цикл получения разделов. Чтобы запрос выдавал только подразделы нужного раздела, и эти подразделы попадали затем в $menuItems['ROOT']. Если подразделы у вас без вложенности, то достаточно добавить в фильтр SECTION_ID. Если вложенность присутствует, то смотрите в сторону LEFT_MARGIN, RIGHT_MARGIN, здесь вам придется сначала отдельным запросом получить сам раздел, чтобы узнать его LEFT_MARGIN, RIGHT_MARGIN.

Alex

16.01.2015 14:50:53

Здравствуйте, а не могли бы Вы предоставить код с .menu_ext.php, если вам не сложно.\
Заранее Спасибо!

Максим

16.01.2015 18:03:52

Alex, добавил пример .menu_ext.php в статью.

Alex

16.01.2015 19:31:27

Максим, большое Вам спасибо!!!!

Алекс

27.02.2015 11:00:08

Максим, добрый день!
Спасибо большое за компонент, очень выручил.
Возник вопрос, не удалось настроить сортировку разделов и элементов между собой.
То есть сначала выводятся разделы и сортируются между собой, а потом выводятся элементы и сортируются между собой.
Есть ли возможно пересортировать элементы и разделы между собой?

Максим

27.02.2015 17:10:58

Алекс, в текущей реализации такой возможности нет. Действительно сначала выводятся разделы, потом элементы.
Для добавления данного функционала можно модернизировать функцию createMenuArray, в начале функции до цикла проводить сортировку массива $arParent, согласно полю SORT

Nosferatv

22.06.2015 17:14:28

Excellent!

Сергей

21.07.2015 12:10:41

Максим, а как сделать вывод картинки раздела в меню? Заранее спасибо.

Максим

21.07.2015 12:50:38

Сергей, в функции createMenuArray задается массив параметров, который будет доступен в шаблоне. Туда можно добавлять картинку раздела. Вот массив доп параметров:

array(
'FROM_IBLOCK' => true,
'IS_PARENT' => $isParent,
'DEPTH_LEVEL' => $depthLevel,
),

Дмитрий

17.09.2015 17:11:35

Огонь още!

Nick

23.09.2015 11:18:52

В новом битриксе пишет menu.sections.elements' is not a component (((

Nick

23.09.2015 11:30:42

Может я не так делаю!??
Создал папку /bitrix/components/Nick/menu.sections.elements

в ней два файла .parameters.php и component.php потом подключил в меню и получил menu.sections.elements' is not a component ... ((

Максим

23.09.2015 12:04:44

Nick, версия битрикса не причем.
Думаю вы к компоненту обращаетесь bitrix:menu.sections.elements или max22:menu.sections.elements, а нужно Nick:menu.sections.elements

Nick здесь это пространство имен компонентов.

Nick

23.09.2015 14:04:16

Думал об этом, специально проверял. Обращение в коде nick:menu.sections.elements т.е. с именами все ок. К сожалению нет опыта работы с битрик возможно всетаки не правильно добавляю компонет, подскажите как правильно это сделать, какие папки и файлы создать?

Максим

23.09.2015 18:58:35

раз папка у вас с большой буквы Nick, значит и в вызове компонента используйте большую Nick:menu.sections.elements

либо попробуйте переименовать папку и назвать все маленькими буквами, т.к. я например, не припомню чтобы видел названия пространств в большой буквы. Но врятли в этом дело.

Может быть, если с именами все ок, то просто у сервера прав на чтение не хватает, например, если апатч из под одного юзера работает, а вы папку из под рута создавали. Но это тоже врятли.

Думаю имеет место быть опечатка или что то в этом роде.

Nick

24.09.2015 03:43:22

Действительно все дело в именах,а именно большая буква N. )))
Подключился компонент, но по-моему что то не так... Если в настройках я ставлю уровень вложенности 1 тогда получаю меню из списка разделов/элементов инфоблока + 1й пункт состоит из раздела/элемента + подразделы + элементы подраздела, т.е. это вроде как лишнее. Т.е. тогда уж и первый пункт должен быть не разворачивающийся.

Если ставлю глубину 2 тогда получаю меню из разделов/элементов и подразделов + элемент подраздела, это уже подходит, но как убрать элементы подразделов?

И еще настройки URL в файле вызова модуля никак не влияют на URL пунктов меню, у меня выдает так .ru/fo_bud_dlia_gragdan/list.php?SECTION_ID=145 fo_bud_dlia_gragdan это тип инфоблока ну верный, ID секции тоже правильный откуда берет list.php ? Вообще должна быть ссылка типа .ru/about/dependents/finansovyy-otdel/byudzhet-dlya-grazhdan/?SECTION_ID=142

Максим

24.09.2015 06:12:10

Nick, Элементы всегда будут подключаться, т.е. если глубина 1, то будут разделы 1-го уровня и их элементы. На выходе имеем 2-х уровневое меню. Если вам нужно другое поведение, то можно в коде компонента добавить необходимые условия.

>И еще настройки URL в файле вызова модуля никак не влияют на URL
там и нет настроек урл, если смотреть файл .parameters.php, просто я в примере вызова забыл убрать эти параметры (сейчас убрал). А Урл должен настраиваться в настройке инфоблока: https://yadi.sk/i/0imlg6vBjHQfa

Nick

24.09.2015 10:09:40

Насчет ULR понял, у меня они настроены под стандартный компонент menu.sections от того и едет.

>Элементы всегда будут подключаться, т.е. если глубина 1, то будут разделы 1-го уровня и их элементы. На выходе имеем 2-х уровневое меню.

Если я не ошибаюсь, сейчас меню работает ни так. Не пойму как поправить код чтобы при глубине 1 не показывались элементы первого пункта меню, и почему именно первый в остальных же не показывает...
Вот скриншоты:

глубина 1 - http://www.picshare.ru/uploads/150924/v5tU2aHGQX.jpg

глубина 2 - http://www.picshare.ru/uploads/150924/AYLc52Uc9l.jpg

Nick

29.09.2015 04:05:40

Все еще мучаю компонент. :)

Насчет сортировки:
Алекс, в текущей реализации такой возможности нет. Действительно сначала выводятся разделы, потом элементы.
Для добавления данного функционала можно модернизировать функцию createMenuArray, в начале функции до цикла проводить сортировку массива $arParent, согласно полю SORT

В массиве нет поля Sort, как его туда добавить??? Подскажите пожалуйста очень хочется настроить все как надо уж больно хороший компонент. :)

Nick

29.09.2015 05:26:59

Видимо сегодня на меня снизошло озарение, добавил поле SORT и отсортировал. Даже убрал лишние разделы из первого пункта меню при глубине 1, но наверно не так как надо, а через кривые костыли.)) Да еще и не ясно как убрать элементы 3го уровня при глубине 2.

Максим

29.09.2015 07:54:59

Nick, попробуйте заменить стороку
$arSectionId[] = $arSection['ID'];

на

if ($arSection['DEPTH_LEVEL'] < $arParams['DEPTH_LEVEL']){
$arSectionId[] = $arSection['ID'];
}

И затем перед
 //Получим элементы

Добавить

if (! $arSectionId) {
$arSectionId = false;
}

Nick

01.10.2015 03:44:32

Спасибо, теперь всё отлично работает! :)

Nick

01.10.2015 08:52:08

Решил добавить в каждый раздел подменю чтобы оно разворачивалось в основном, но как оказалось я могу добавить меню только в одном разделе, если добавляю в еще один раздел то получаю белый экран, т.е. ошибку.
Вот здесь описал подробно проблему http://dev.1c-bitrix.ru/community/forums/messages/forum6/topic75312/message390070/index.php#message390070
это может быть ошибка в компоненте???

Nick

06.10.2015 05:18:44

Оказывается это я намудрил с функцией сортировки, она выдавала ошибку...

Подскажите, вот у меня когда я нахожусь в каком нибудь разделе инфоблока меню разворачивает полностью все пункты меню до указанной в настройках глубины, это так задумано или у меня проблема с шаблоном?
При этом свернуть развернутые пункты я не могу при нажатии на пункт просто меняется значек напротив пункта,а сам пункт меню не сворачивается...

Нуб

13.10.2015 14:10:26

Помогите с такой проблемой: на сайт публикуются новости, они сохраняются и выводятся в списке, но на главную почему-то не попадают. В чем может быть дело?

foxufo

20.10.2015 12:34:29

Огромное спасибо.. т.к. начал у же сам писать компонент..
а почему именно так htmlspecialchars($item['~NAME']), у меня так пустые названия получились.. заменил на $item['NAME'] и все хорошо..

Nikolay

02.12.2015 15:40:13

Спасибо большое! Ваш код сразу заработал. О боже как же я матерюсь работаю с меню битрикса. Каких только костылей не придумывал.

Евгений

18.12.2015 01:34:28

Здравствуйте. Спасибо большое. Супер решение. Все заработало и еще, ваш код помог немного разобраться с устройством системы. Может подскажете - как сделать так чтобы верхним уровнем был инфоблок, затем разделы, затем элементы.

Евегний

27.12.2015 22:15:49

Отвечу себе сам. Я допер как это можно сделать - добавить верхний уровень, т.е. инфоблок в меню.
Не знаю насколько правильно, возможно это жуткий костыль, но он работает.

В компонент, перед вызовом функции createMenuArray добавляем
$iblock=CIBlock::GetArrayByID($arParams['IBLOCK_ID'],""); //получаем инфоблок
$link='/'.$iblok['CODE'].'/'; //получаем ссылку из кода инфоблока, тут, наверно надо проверять включен ли ЧПУ, у меня включен, поэтому не проверяю
$name=htmlspecialchars($iblock['NAME']); //получаем имя, у меня оно почему-то ////составное - [s1] Услуги, поэтому следующий шаг
$name=explode(" ", $name); // разбиваем имя на части
$iblock1= array('NAME'=>$name[1],'LINK'=>$link);//формируем массив
$firsttime=TRUE; //маркер первого запуска, т.к. функция рекурсивная
createMenuArray($arResult,$menuItems,$menuItems['ROOT'],1,$iblok1,$firsttime);

и в самой функции перед циклом перебора массивов добавил
if ($ft){
$res[] = array(
htmlspecialchars($iblock['NAME']),
$iblock['LINK'],
array(), //массив доп ссылок
array(
'FROM_IBLOCK' => true,
'IS_PARENT' => 1,
'DEPTH_LEVEL' => 1,
),
);
$ft = FALSE;
}

Кирилл

07.03.2016 08:22:28

Огромное спасибо, решение то что нужно, для такого новичка как я все разжевано в комментариях. Еще раз СПАСИБО!

Дмитрий

01.06.2016 10:18:33

Огромное спасибо!!! Я запарился искать решение этой проблемы и тут подарок!))
Еще раз благодарю)

Алеша

06.07.2016 16:10:26

Макс, всё бы хорошо в статьях. Но для таких примеров не хватает "Скачать исходный код". Как говорится - зачем ctrlC,ctrlV - если можно скачать и положить - при необходимости допилить :)

gagra33332

04.09.2016 03:46:10

Подскажите а как правильно и где надо прописать чтобы изображения разделов отображались

Jack

01.11.2016 16:56:48

Сделал меню по вашему примеру. Действительно, отображает и разделы, и каталоги. НО! При нажатии на ссылки (и раздел, и каталог) попадаешь на корневую страницу каталога, а не внутрь него. Что может быть не так?

Jack

01.11.2016 18:10:36

Со ссылками разобрался. Но вот еще проблема: в финале скопировал шаблон меню в папку default (как обычно). А как там отличить названия разделов инфоблока и названия его элементов. А то к ним один и тот же стиль применяется.

Максим

02.11.2016 05:26:16

Jack, в коде компонента можете доработать функцию createMenuArray. Именно она создает элементы меню, которые приходят в шаблон.
в массив параметров добавьте параметра IS_SECTION => $item['IS_SECTION'], вот так:

array(
'FROM_IBLOCK' => true,
'IS_PARENT' => $isParent,
'DEPTH_LEVEL' => $depthLevel,
'IS_SECTION' => $item['IS_SECTION'],
),

В шаблоне по этому параметру будете определять раздел это или нет.

PS Что за проблема была со ссылками? Шаблоны пути были не указаны в настройках инфоблока?

Jack

02.11.2016 10:15:49

Максим
Со ссылками - да, раньше я выводил элементы каталога более тривиальными способами и меня устраивали дефотлные пути, потписанные его разделам:
#SITE_DIR#/catalog/index.php?ID=#IBLOCK_ID#
#SITE_DIR#/catalog/list.php?SECTION_ID=#SECTION_ID#
#SITE_DIR#/catalog/detail.php?ID=#ELEMENT_ID#

Для вашего меню пришлось поправить, но теперь вроде все заработало, осталось разобраться с внешним видом.

А вообще очень здорово вы сделали. Я перебрал 3 или 4 варианта этого кастомного компонента и ни один нормально не работал.

Jack

02.11.2016 16:47:52

Еще вопрос. Я добавил параметр, но не могу сообразать, где он заполняется. Если его просто добавить - потом при проверке оказывается, что у всех членов массива он равен 0. Проверяю так:

<?if($arFields['IS_SECTION'] == 1):?>
<li><a href="<?=$arItem["LINK"]?>" class="SubMenu"><?=$arItem["TEXT"]?></a></li>
<?else:?>
<li><a href="<?=$arItem["LINK"]?>" class="vert_menu"><?=$arItem["TEXT"]?></a></li>
<?endif?>

Максим

02.11.2016 16:58:13

Команда чтобы посмотреть что в массиве:

echo '<pre>'.print_r($arItem,true).'</pre>';

Я первым делам в шаблоне пишу:

echo '<pre>'.print_r($arResult,true).'</pre>';

Смотрю что приходит из компонента.

Jack

02.11.2016 17:17:26

Посмотрела, похоже, что IS_SECTION все-таки заполняется правильно:

Array
(
[0] => Array
(
[TEXT] => Рекламная продукция
[LINK] => /catalog/1
[SELECTED] =>
[PERMISSION] => X
[ADDITIONAL_LINKS] => Array
(
)

[ITEM_TYPE] => P
[ITEM_INDEX] => 0
[PARAMS] => Array
(
[FROM_IBLOCK] => 1
[IS_PARENT] => 1
[DEPTH_LEVEL] => 1
[IS_SECTION] => 1
)

[DEPTH_LEVEL] => 1
[IS_PARENT] => 1
)

[1] => Array
(
[TEXT] => Папки
[LINK] => /catalog/1/papki
[SELECTED] =>
[PERMISSION] => X
[ADDITIONAL_LINKS] => Array
(
)

[ITEM_TYPE] => P
[ITEM_INDEX] => 1
[PARAMS] => Array
(
[FROM_IBLOCK] => 1
[IS_PARENT] =>
[DEPTH_LEVEL] => 2
[IS_SECTION] => 0
)

[DEPTH_LEVEL] => 2
[IS_PARENT] =>
)



Но почему тогда при фильтрации они не различаются. Может, неправильно обращаюсь? Как писать:
<?if($arFields['IS_SECTION'] == 1):?>
или
<?if($arParams['IS_SECTION'] == 1):?>

Максим

02.11.2016 18:25:58


<?if($arItem['PARAMS']['IS_SECTION'] == 1):?>

Jack

03.11.2016 10:29:57

Спасибо! Все получилось. Может, стоит добавить это в пример?

Сергей

08.11.2016 20:55:00

Спасибо, пригодилось.

Валентина

16.11.2016 22:30:39

Спасибо огромное!!!

Асем

13.01.2017 12:54:21

Добрый день! я вывела все разделы инфоблока, но мне нужны все кроме одного. Не подскажете, как и где это указать?
Спасибо!

Максим

13.01.2017 15:00:23

Здравствуйте!
Вам нужно в админке к разделу добавить пользовательское свойство с типом да/нет, задать код свойства, например, UF_NOT_SHOW_IN_MENU, проставить галочку на разделе, который вам не нужен в меню.
затем фильтр по разделам изменить следующим образом:

$arFilter = array(
'IBLOCK_ID'=>$arParams['IBLOCK_ID'],
'GLOBAL_ACTIVE'=>'Y',
'ACTIVE'=>'Y',
'UF_NOT_SHOW_IN_MENU' => false,
'<=DEPTH_LEVEL' => $arParams['DEPTH_LEVEL'],
);

Асем

16.01.2017 07:07:21

Максим, спасибо большое!

Олег

16.01.2017 15:20:36

Здравствуйте.
А как вывести элементы, которые привязаны к нескольким разделам? Сейчас выводятся только те, которые находятся в одном разделе

Максим

17.01.2017 06:37:04

Олег, для этого нужно изменить код:

if ($arFields['IBLOCK_SECTION_ID']){
$menuItems[$arFields['IBLOCK_SECTION_ID']][] = $arFields;
} else {
$menuItems['ROOT'][] = $arFields;
}

В коде берется основной раздел IBLOCK_SECTION_ID, а вам нужно добавить цикл - обход всех разделов элемента. Получить их можно с помощью:
CIBlockElement::GetElementGroups

Авель

17.01.2017 10:48:02

Спасибо!

Асем

14.02.2017 10:01:25

Добрый день, Максим! Не подскажете как можно связать 2 свойства инфоблока, чтобы при выборе значения одного свойства, в другом свойстве оставались только варианты относящиеся к выбранному первому свойству (связанные списки)?

Виктор

01.04.2017 19:34:07

Здравствуйте. Подскажите, а что нужно добавить чтобы подсвечивался текущий элемент меню?

Максим

02.04.2017 06:57:22

Асем, если связка нужна в админке, то нужно создать свое кастомное свойство. По сути - это будет выбор из инфоблока - связки (лучше Highload использовать), но в виде двух селектов. При изменении 1-го селекта на js менять элементы второго селекта, а второй селект - уже выбирает значения из инфоблока связки.

Информация о про создание кастомных типов свойств ИБ

Виктор, за подсвечивание отвечает компонент menu, в данном примере мы делаем компонент menu_ext - который только добавляет в меню пункты.

Степан

03.09.2017 19:44:29

Здравствуйте, подскажите пожалуйста как сделать что выводились только разделы и подразделы?

Максим

26.01.2018 15:43:55

Добрый день, Максим. Подскажите как вывести свойство элемента. Например текст анонса.

Ulugbek Pulatov

14.03.2018 10:25:25

Здравствуйте! посоветуйте пожалуйста...

есть раздел services в меню который тянет всю информацию с инфоблока - я его закрыл добавив в коней папки /index.php
теперь стоит задача вытащить в подпункт только нужные папки... ручная правка левого меню дает результат только с боковой позиции.. на главную не выходить...

что можно сделать пожалуйста подскажите

Николай

07.06.2018 08:06:13

Здравствуйте!

Подскажите,а как можно реализовать загрузку пунктов меню только по указанному разделу инфоблока?

Желательно чтобы можно было в коде файла меню указывать раздел инфоблока, например добавив SECTION_ID:

[...Код вырезал для экономии места...]

К сожалению не очень дружу с php, если можно покажите пример кода.

Николай

07.06.2018 09:23:14

Как добавить параметр в конпонент я разобрался, вроде бы сделал верно: "SECTION_ID" => array( "NAME" => GetMessage("SECTION_ID_VARIABLE_PHR"), Не пойму как сделать фильтр в компоненте по этому параметры, компонент у меня измененный: 

[...Много кода вырезал для экономии места...]

Максим

07.06.2018 11:28:38

Николай, фильтровать разделы с подразделами по разделу родителю нужно с помощью полей LEFT_MARGIN, RIGHT_MARGIN принцип следующий:


1. Получаете родительский раздел по SECTION_ID, у него получаете поля LEFT_MARGIN, RIGHT_MARGIN.


2. Получаете подразделы данного раздела учитывая что LEFT_MARGIN раздела-потомка > LEFT_MARGIN раздела-родителя и RIGHT_MARGIN раздела-потомка < RIGHT_MARGIN раздела-родителя.


Вот ссылка на пример на сайте битрикса: https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblocksection/getlist.php#ex4

Николай

07.06.2018 11:42:10

Максим, спасибо за подсказку.
Вариантов фильтрации наверняка есть множество, к сожалению я не могу понять как их применить к конкретному коду компонента.
Честно говоря уже методом тыка ставил разные условия в разные места кода, но ничего не выходит, увы знаний не хватает...(((

Николай

08.06.2018 04:44:41

В общем, получается так, что меню в параметрах которого указан подраздел и при получении свойств LEFT_MARGIN, RIGHT_MARGIN не возвращается пустое значение, фильтрация работает.
НО те меню в параметрах меню НЕ указан подраздел, т.к. там фильтрация по нему не нужна, не заполняются.

Как сделать, чтобы фильтр работал только когда в параметрах задан подраздел?

Сейчас код у меня выглядит так:

// получение свойств LEFT_MARGIN, RIGHT_MARGIN
// по ID раздела
$arLM = 0;
$arRM = 0;
$res1 = CIBlockSection::GetByID($arParams['SECTION_ID']);
if($ar_res = $res1->GetNext()) {
"<pre>";

$arLM = $ar_res['LEFT_MARGIN'];
$arRM = $ar_res['RIGHT_MARGIN'];
/* echo "SECTION_ID=" ;
echo $arParams['SECTION_ID'] ;
echo "/" ;
echo "LEFT_MARGIN=" ;
echo $ar_res['LEFT_MARGIN'] ;
echo "/" ;
echo "RIGHT_MARGIN=";
echo $ar_res['RIGHT_MARGIN'] ;
echo "arLM=" ;
echo $arLM ;
echo "/" ;
echo "arRM=";
echo $arRM;*/

}


//echo "<pre>"; print_r($ar_res); echo "</pre>";
// конец получения свойств LEFT_MARGIN, RIGHT_MARGIN




if($arParams['DEPTH_LEVEL']<=0)
$arParams['DEPTH_LEVEL']=1;

if($this->StartResultCache()) {
CModule::IncludeModule('iblock');
$arSectionId = array();
$arFilter = array(
'IBLOCK_ID'=>$arParams['IBLOCK_ID'],
'GLOBAL_ACTIVE'=>'Y',
'ACTIVE'=>'Y',
'<=DEPTH_LEVEL' => $arParams['DEPTH_LEVEL'],
//фильтрация разделов по родителю!!!
'LEFT_MARGIN'=>$arLM,
'RIGHT_MARGIN'=> $arRM,
);
$arOrder = array(
'SORT'=>'ASC',
);
$rsSections = CIBlockSection::GetList($arOrder, $arFilter, false, array(
'ID',
'DEPTH_LEVEL',
'NAME',
'SECTION_PAGE_URL',
'IBLOCK_SECTION_ID',
'SORT',
));
$menuItems = array();

Максим

08.06.2018 05:50:19

Николай, идете по верному пути, сделайте следующее:
Там где получаете основной фильтр $arFilter (после if($this->StartResultCache()) )
уберите из фильтра LEFT_MARGIN, RIGHT_MARGIN, а сразу ниже добавьте условие: если заполнен $arParams['SECTION_ID'], то получаем LEFT_MARGIN, RIGHT_MARGIN и добавляем в фильтр. Будет примерно так:

if($this->StartResultCache()) {
CModule::IncludeModule('iblock');
$arSectionId = array();
$arFilter = array(
'IBLOCK_ID'=>$arParams['IBLOCK_ID'],
'GLOBAL_ACTIVE'=>'Y',
'ACTIVE'=>'Y',
'<=DEPTH_LEVEL' => $arParams['DEPTH_LEVEL'],
);
if ($arParams['SECTION_ID']){
[ВАШ БЛОК С ПОЛУЧЕНИЕМ LEFT_MARGIN, RIGHT_MARGIN]
//подставляем их в фильтр
$arFilter['>LEFT_MARGIN'] = $arLM;
$arFilter['<RIGHT_MARGIN '] = $arRM;
}
[ПРОДОЛЖЕНИЕ КОДА]

PS из начала убираем [ВАШ БЛОК С ПОЛУЧЕНИЕМ LEFT_MARGIN, RIGHT_MARGIN]

Николай

08.06.2018 06:23:43

Использовал Ваш код

if ($arParams['SECTION_ID']){
[ВАШ БЛОК С ПОЛУЧЕНИЕМ LEFT_MARGIN, RIGHT_MARGIN]
//подставляем их в фильтр
$arFilter['>LEFT_MARGIN'] = $arLM;
$arFilter['<RIGHT_MARGIN '] = $arRM;
}

тоже самое, если указан раздел первого уровня то работает, если второго и последующих тогда меню не формируется.

Максим

08.06.2018 06:28:29

Николай,
вот эту строку замените:
createMenuArray($arResult,$menuItems,$menuItems['ROOT'],1);

на

if ($arParams['SECTION_ID']){
createMenuArray($arResult,$menuItems,$menuItems[$arParams['SECTION_ID']],1);
} else {
createMenuArray($arResult,$menuItems,$menuItems['ROOT'],1);
}

Николай

08.06.2018 06:49:32

Максим, спасибо огромное. Вроде бы получилось. :)

Не выводятся пункты меню на странице раздела

14.01.2019 15:20:25

Уже всю голову сломал. Страницы содержимого разделов инфоблока выводятся по ссылкам http://domen/imya_razdela/, элементы раздела выводятся по ссылкам типа http://domen/imya_elementa.html.
Добавил меню в шаблон обеих страниц. Оба шаблона для этих страниц лежат в корне сайта, рядом с ними же лежат файлы .left.menu_ext.php и .left.menu.php. Меню нормально выводится на странице элемента, и не выводит все пункты на странице раздела...
В чем может быть причина?

Trioka

20.02.2021 20:49:48

Зашибись, просто вставил и всё заработало, без всяких извращений.

Максим

08.04.2021 10:43:20

СПАСИБО!!!!

Евгений

11.07.2021 22:23:01

Работает, сначала кидал компонент в папку с шаблоном, не работало, закинул в корневую папку bitrix/components/bitrix/ сразу заработало.

Сергей

31.08.2021 23:58:39

Здравствуйте.
Не получается использовать ваш компонент.
лог ошибок:
[Error]
Undefined constant "createMenuArray" (0)
/home/c/cb54090/public_html/bitrix/components/leftmenu/menu.sections.elements/component.php:2
#0: include
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/component.php:605
#1: CBitrixComponent->__includeComponent()
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/component.php:682
#2: CBitrixComponent->includeComponent(string, array, boolean, boolean)
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/main.php:1068
#3: CAllMain->IncludeComponent(string, string, array, boolean, array)
/home/c/cb54090/public_html/.left.menu_ext.php:33
#4: include(string)
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/menu.php:115
#5: CMenu->Init(string, boolean, string)
/home/c/cb54090/public_html/bitrix/components/bitrix/menu/component.php:53
#6: include(string)
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/component.php:605
#7: CBitrixComponent->__includeComponent()
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/component.php:103
#8: CBitrixComponent->executeComponent()
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/component.php:658
#9: CBitrixComponent->includeComponent(string, array, boolean, boolean)
/home/c/cb54090/public_html/bitrix/modules/main/classes/general/main.php:1068
#10: CAllMain->IncludeComponent(string, string, array, boolean)
/home/c/cb54090/public_html/bitrix/templates/gidrosv/header.php:141
#11: include_once(string)
/home/c/cb54090/public_html/bitrix/modules/main/include/prolog_after.php:106
#12: require(string)
/home/c/cb54090/public_html/bitrix/modules/main/include/prolog.php:11
#13: require_once(string)
/home/c/cb54090/public_html/bitrix/header.php:1
#14: require(string)
/home/c/cb54090/public_html/index.php:2

Подскажите куда копать?

Максим

01.09.2021 08:38:33

Сергей, в строке
if (!function_exists('createMenuArray')){
createMenuArray возьмите в кавычки.
Сам пример исправил.
Ошибка зависит от конфигурации php, но кавычки здесь должны были быть изначально, упустил.

Андрей

25.03.2022 19:28:26

Здравствуйте!

У меня получились ссылки ввида: /IDкатегории/IDвложенной категории/
Но если есть вложенная категория почему-то нет ссылки на родительскую категорию (только ее название). В чем проблема?

Здравствуйте!

12.03.2024 23:55:19

как сделать такое меню раскрывающееся как на этом сайте с плюсом и минусом? у меня никак не получается

Оставить комментарий:

Представьтесь пожалуйста:
Электронная почта:
Электронный адрес не публикуются
Текст сообщения:
Для подсветки кода, оборачивайте ваш код в теги <code></code>
Введите 5 цифр с картинки:

Рекомендую:

Поделюсь промокодами для хостинга TimeWeb!

Поддержать проект: