Июл
26
2021

Как вывести элементы инфоблока в меню Битрикс

Элементы меню в Битрикс хранятся в специальных файлах с именем .тип_меню.menu.php. Динамические пункты, то есть те, которые выводятся из базы данных, в файлах .тип_меню.menu_ext.php.

Для вывода разделов инфоблока в меню есть компонент bitrix:menu.sections. А вот для вывода элементов, компонента нет.

Давайте выведем разделы и элементы, которые не прикреплены к разделам, в меню.

Хотим, чтобы пункты добавились выпадающими к основному пункту Каталог. Если нужный нам пункт ведет на страницу /catalog/, то и меню с выпадающими пунктами должно быть в этой папке.

Тип меню, который требуется создавать можно узнать в параметрах вызова компонента bitrix:menu. Смотрим значение CHILD_MENU_TYPE. Обычно это left.

Значит создаем файл "/catalog/.left.menu_ext.php".

В файле сделаем получение разделов через компонент bitrix:menu.sections и получение элементов через CIBlockElement::GetList(). Сделаем сразу кеширование, чтобы не нагружать базу данных лишними запросами. А чтобы кеш сбрасывался, когда мы добавляем или изменяем элементы в нашем инфоблоке, добавим теги к кешу. Кеш компонента bitrix:menu.sections выключим, так как у нас и так есть кеширование. В фильтре CIBlockElement::GetList укажем ID инфоблока, элементы брать только из корня и только активные в порядке сортировки.

Код файла .left.menu_ext.php:

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

use \Bitrix\Main\Data\Cache;
use \Bitrix\Main\Application;

$iblockId = 2;

$cache = Cache::createInstance();
$taggedCache = Application::getInstance()->getTaggedCache();

$cachePath = 'top_menu_iblock_' . $iblockId;

if ($cache->initCache(36000, $cachePath, $cachePath))
{
	$aMenuLinksExt = $cache->getVars();
}
elseif ($cache->startDataCache())
{
	$taggedCache->startTagCache($cachePath);
	
	$aMenuLinksExt = $APPLICATION->IncludeComponent(
		"bitrix:menu.sections",
		"",
		Array(
			"ID" => "", 
			"IBLOCK_TYPE" => "products",
			"IBLOCK_ID" => $iblockId, 
			"SECTION_URL" => "", 
			"DEPTH_LEVEL" => "1", 
			"CACHE_TYPE" => "N", 
			"CACHE_TIME" => "3600" 
		)
	);
	
	$res = CIBlockElement::GetList (
		['SORT' => 'ASC'],
		["IBLOCK_ID" => $iblockId, "IBLOCK_SECTION_ID" => false, 'ACTIVE' => 'Y'],
		false,
		false
	);
	
	$aMenuProducts = [];
	while($element = $res->GetNext())
	{
		$aMenuLinksExt[] = [
			$element['NAME'],
			$element['DETAIL_PAGE_URL'],
			[$element['DETAIL_PAGE_URL']],
			[
				'FROM_IBLOCK' => true,
				'IS_PARENT' => false,
				'DEPTH_LEVEL' => '1',
			]
		];
	}
	
	
	$taggedCache->registerTag("iblock_id_{$iblockId}");
	$taggedCache->endTagCache();
	$cache->endDataCache($aMenuLinksExt);
}

$aMenuLinks = array_merge($aMenuLinks, $aMenuLinksExt);
?>

У нас получилось в меню вначале идут разделы и после элементы. А что если мы хотим какие-то элементы выводить над ссылками разделов?

Тогда надо сделать сортировку полученных разделов и элементов между собой по полю SORT. Увы, стандартный bitrix:menu.sections не возвращает значение сортировки раздела. Придется копировать компонент в свое пространство.

Копируем содержимое папки /bitrix/component/bitrix/menu.sections в /local/component/my/menu.sections. В папке local в скопированном компоненте открываем файл component.php. Добавляем работу с сортировкой как на картинках.

Теперь изменим файл .left.menu_ext.php:

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

use \Bitrix\Main\Data\Cache;
use \Bitrix\Main\Application;

$iblockId = 2;

$cache = Cache::createInstance();
$taggedCache = Application::getInstance()->getTaggedCache();

$cachePath = 'top_menu_products';

if ($cache->initCache(36000, $cachePath, $cachePath))
{
	$aMenuLinksExt = $cache->getVars();
}
elseif ($cache->startDataCache())
{
	$taggedCache->startTagCache($cachePath);
	
	$aMenuLinksExt = $APPLICATION->IncludeComponent(
		"bitrix:menu.sections",
		"",
		Array(
			"ID" => "", 
			"IBLOCK_TYPE" => "products",
			"IBLOCK_ID" => $iblockId, 
			"SECTION_URL" => "", 
			"DEPTH_LEVEL" => "1", 
			"CACHE_TYPE" => "N", 
			"CACHE_TIME" => "3600" 
		)
	);
	
	$res = CIBlockElement::GetList (
		[],
		["IBLOCK_ID" => $iblockId, "IBLOCK_SECTION_ID" => false, 'ACTIVE' => 'Y'],
		false,
		false
	);
	
	$aMenuProducts = [];
	while($element = $res->GetNext())
	{
		$aMenuLinksExt[] = [
			$element['NAME'],
			$element['DETAIL_PAGE_URL'],
			[$element['DETAIL_PAGE_URL']],
			[
				'FROM_IBLOCK' => true,
				'IS_PARENT' => false,
				'DEPTH_LEVEL' => '1',
				'SORT' => $element['SORT'],
			]
		];
	}
	
	usort($aMenuLinksExt, function($a, $b){
		if (is_null($a[3]['SORT'])) $a[3]['SORT'] = 0;
		if (is_null($b[3]['SORT'])) $b[3]['SORT'] = 0;
		
		if ($a[3]['SORT'] === $b[3]['SORT'])
		{
			return 0;
		}
		
		return ($a[3]['SORT'] < $b[3]['SORT']) ? -1 : 1;
	});
	
	$taggedCache->registerTag("iblock_id_{$iblockId}");
	$taggedCache->endTagCache();
	$cache->endDataCache($aMenuLinksExt);
}

$aMenuLinks = array_merge($aMenuLinks, $aMenuLinksExt);
?>

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

Пожалуйста, оцените на сколько вам понравилась статья!
Голосов: 6 Среднее: 4