Yandex Metrika
sanches.free 1 просмотр

Элементы инфоблока в меню Битрикс: разделы и корень каталога

Файлы меню: статические и расширенные

Пункты навигации в «1С-Битрикс» задаются наборами .menu.php рядом с разделами сайта. Если нужно подмешать данные из инфоблока, добавляют соседний файл с суффиксом _ext — именно там удобно собирать ссылки через PHP без ручного редактирования меню после каждой правки контента.

Разделы и «корневые» карточки рядом с каталогом

Готовый вывод деревьев разделов уже закрывает компонент bitrix:menu.sections. Отдельного штатного блока только для элементов нет — поэтому цепочка обычно такая: сначала тянем разделы через компонент, затем выборкой CIBlockElement::GetList добавляем активные элементы без привязки к разделу (фильтр по пустому IBLOCK_SECTION_ID).

Чтобы подменю «подвешивалось» к пункту вида Каталог, файл расширения кладётся в ту же директорию, что открывает страницу каталога, например /catalog/.left.menu_ext.php для типа, указанного в CHILD_MENU_TYPE основного меню (часто это left).

Пример файла расширения с кешем и тегами

Ниже — базовый сценарий: разделы из компонента, затем элементы из корня инфоблока, собранные в том же массиве пунктов и объединённые с уже существующими $aMenuLinks. Чтобы запросы к базе не били при каждом хите, включён управляемый кеш и тег iblock_id_* для автоматической инвалидации при изменении инфоблока. У компонента разделов кеш отключён — он не дублирует общую стратегию.

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

global $APPLICATION;

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

$inventoryBlockId = 8;

$navCacheHandle = Cache::createInstance();
$tagEngine = Application::getInstance()->getTaggedCache();

$navBucketKey = 'catalog_nav_fusion_' . $inventoryBlockId;

if ($navCacheHandle->initCache(36000, $navBucketKey, $navBucketKey)) {
    $menuExtensionItems = $navCacheHandle->getVars();
} elseif ($navCacheHandle->startDataCache()) {
    $tagEngine->startTagCache($navBucketKey);

    $menuExtensionItems = $APPLICATION->IncludeComponent(
        'bitrix:menu.sections',
        '',
        [
            'ID' => '',
            'IBLOCK_TYPE' => 'trade_offers',
            'IBLOCK_ID' => $inventoryBlockId,
            'SECTION_URL' => '',
            'DEPTH_LEVEL' => '1',
            'CACHE_TYPE' => 'N',
            'CACHE_TIME' => '3600',
        ]
    );

    $rootRows = CIBlockElement::GetList(
        ['SORT' => 'ASC', 'NAME' => 'ASC'],
        [
            'IBLOCK_ID' => $inventoryBlockId,
            'IBLOCK_SECTION_ID' => false,
            'ACTIVE' => 'Y',
        ],
        false,
        false,
        ['ID', 'NAME', 'DETAIL_PAGE_URL']
    );

    while ($item = $rootRows->GetNext()) {
        $url = $item['DETAIL_PAGE_URL'];
        $menuExtensionItems[] = [
            $item['NAME'],
            $url,
            [$url],
            [
                'FROM_IBLOCK' => true,
                'IS_PARENT' => false,
                'DEPTH_LEVEL' => '1',
            ],
        ];
    }

    $tagEngine->registerTag('iblock_id_' . $inventoryBlockId);
    $tagEngine->endTagCache();
    $navCacheHandle->endDataCache($menuExtensionItems);
}

$aMenuLinks = array_merge($aMenuLinks, $menuExtensionItems);

Общая сортировка с разделами

В таком виде блок из компонента и материалы из базы просто дописываются друг за другом. Если нужно «перемешать» раздел и карточку по полю сортировки, придётся, чтобы число SORT было доступно для всех элементов строки меню.

Стандартный menu.sections может не пробрасывать сортировку разделов в финальный массив — типичное решение: скопировать компонент в /local/components/custom/menu.sections/, аккуратно добавить нужное поле при построении ссылок, а в меню подключить уже свой вариант через custom:menu.sections. После этого один проход usort по индексу SORT в параметрах пункта выравнивает порядок: меньший SORT поднимает ссылку выше, в том числе над соседним разделом.

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

global $APPLICATION;

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

$inventoryBlockId = 8;

$navCacheHandle = Cache::createInstance();
$tagEngine = Application::getInstance()->getTaggedCache();

$navBucketKey = 'catalog_nav_mixed_' . $inventoryBlockId;

if ($navCacheHandle->initCache(36000, $navBucketKey, $navBucketKey)) {
    $menuExtensionItems = $navCacheHandle->getVars();
} elseif ($navCacheHandle->startDataCache()) {
    $tagEngine->startTagCache($navBucketKey);

    $menuExtensionItems = $APPLICATION->IncludeComponent(
        'custom:menu.sections',
        '',
        [
            'ID' => '',
            'IBLOCK_TYPE' => 'trade_offers',
            'IBLOCK_ID' => $inventoryBlockId,
            'SECTION_URL' => '',
            'DEPTH_LEVEL' => '1',
            'CACHE_TYPE' => 'N',
            'CACHE_TIME' => '3600',
        ]
    );

    $flatElements = CIBlockElement::GetList(
        [],
        [
            'IBLOCK_ID' => $inventoryBlockId,
            'IBLOCK_SECTION_ID' => false,
            'ACTIVE' => 'Y',
        ],
        false,
        false,
        ['ID', 'NAME', 'DETAIL_PAGE_URL', 'SORT']
    );

    while ($item = $flatElements->GetNext()) {
        $rank = isset($item['SORT']) ? (int)$item['SORT'] : 0;
        $url = $item['DETAIL_PAGE_URL'];
        $menuExtensionItems[] = [
            $item['NAME'],
            $url,
            [$url],
            [
                'FROM_IBLOCK' => true,
                'IS_PARENT' => false,
                'DEPTH_LEVEL' => '1',
                'SORT' => $rank,
            ],
        ];
    }

    usort($menuExtensionItems, static function ($left, $right) {
        $a = isset($left[3]['SORT']) ? (int)$left[3]['SORT'] : 0;
        $b = isset($right[3]['SORT']) ? (int)$right[3]['SORT'] : 0;

        return $a <=> $b;
    });

    $tagEngine->registerTag('iblock_id_' . $inventoryBlockId);
    $tagEngine->endTagCache();
    $navCacheHandle->endDataCache($menuExtensionItems);
}

$aMenuLinks = array_merge($aMenuLinks, $menuExtensionItems);

Что помнить перед выкладкой

  • Значение $inventoryBlockId и символьный код типа инфоблока замените на реальные из административной панели.
  • Скопируйте ядросный компонент целиком, не вырезая зависимости, и включите свой вариант только после локального теста.
  • Разумный TTL кеша и тегирование сберегут производительность и не потребуют ручного сброса после правок элементов.

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

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии