1. Главная
  2. Блог
  3. 1С-Битрикс
  4. Выводим подразделы каталога на верхний уровень

Выводим подразделы каталога на верхний уровень

В проектах на 1С-Битрикс с шаблонами Aspro часто возникает задача: вывести отдельные подразделы каталога (второго уровня) на первый уровень — например, в меню или в списке разделов.

При этом важно сохранить:

  • структуру URL (вложенность разделов)
  • привязку к родителю в инфоблоке
  • корректную сортировку

В этой статье рассмотрим два решения:

  • для меню каталога
  • для списка разделов (catalog.section.list)

1. Задача

меню

Есть структура каталога:

  • Швейное оборудование
    • Оверлоки (overloki)
    • Распошивальные машины (rasposhivalnye_mashiny)

Нужно:

  • оставить структуру как есть (для SEO и URL)
  • но вывести эти разделы как будто они находятся в первом уровне

    2. Решение для меню каталога (Aspro Max / Next)

    Решение реализуется в result_modifier.php меню.

    Логика:

    • находим нужные разделы во втором уровне
    • удаляем их из вложенности
    • добавляем в первый уровень
    • вставляем по SORT из инфоблока

    Код решения

    
    // какие разделы поднимаем
    $promoteSectionCodes = array(
        'overloki',
        'rasposhivalnye_mashiny',
    );
    
    // получить код раздела из пункта меню
    function getMenuSectionCode($item){
        if (!empty($item['PARAMS']['CODE'])) return $item['PARAMS']['CODE'];
        if (!empty($item['PARAMS']['SECTION_CODE'])) return $item['PARAMS']['SECTION_CODE'];
        if (!empty($item['CODE'])) return $item['CODE'];
    
        if (!empty($item['LINK'])) {
            $path = trim(parse_url($item['LINK'], PHP_URL_PATH), '/');
            $parts = explode('/', $path);
            return end($parts);
        }
    
        return '';
    }
    
    // получить SORT из инфоблока
    function getSectionSort($iblockId, $code){
        static $cache = [];
    
        $key = $iblockId.'|'.$code;
        if (isset($cache[$key])) return $cache[$key];
    
        $res = CIBlockSection::GetList([], [
            'IBLOCK_ID' => $iblockId,
            'CODE' => $code,
            'GLOBAL_ACTIVE' => 'Y'
        ], false, ['SORT']);
    
        if ($row = $res->Fetch()) {
            return $cache[$key] = (int)$row['SORT'];
        }
    
        return $cache[$key] = 500;
    }
    
    // перенос
    foreach ($arResult as $rootKey => $rootItem) {
    
        if (empty($rootItem['CHILD'])) continue;
    
        $promoted = [];
    
        foreach ($rootItem['CHILD'] as $parentKey => $parentItem) {
    
            if (empty($parentItem['CHILD'])) continue;
    
            foreach ($parentItem['CHILD'] as $childKey => $childItem) {
    
                $code = getMenuSectionCode($childItem);
    
                if (in_array($code, $promoteSectionCodes)) {
                    $promoted[$code] = $childItem;
                    unset($arResult[$rootKey]['CHILD'][$parentKey]['CHILD'][$childKey]);
                }
            }
        }
    
        foreach ($promoteSectionCodes as $code) {
    
            if (!isset($promoted[$code])) continue;
    
            $item = $promoted[$code];
            $sort = getSectionSort($item['PARAMS']['IBLOCK_ID'], $code);
    
            $insertIndex = count($arResult[$rootKey]['CHILD']);
    
            foreach ($arResult[$rootKey]['CHILD'] as $i => $lvl1) {
                $lvlCode = getMenuSectionCode($lvl1);
                $lvlSort = getSectionSort($item['PARAMS']['IBLOCK_ID'], $lvlCode);
    
                if ($lvlSort > $sort) {
                    $insertIndex = $i;
                    break;
                }
            }
    
            array_splice($arResult[$rootKey]['CHILD'], $insertIndex, 0, [$item]);
        }
    
        break;
    }
    

    меню


    3. Решение для списка разделов (catalog.section.list)

    В компоненте catalog.section.list нужные разделы часто просто не попадают в результат.

    Поэтому здесь применяется другая стратегия:

    • загружаем нужные разделы напрямую из инфоблока
    • добавляем их в массив верхнего уровня
    • вставляем по SORT

    Код решения

    
    $promoteSectionCodes = array(
        'overloki',
        'rasposhivalnye_mashiny',
    );
    
    $additionalSections = [];
    
    $rs = CIBlockSection::GetList(
        ['SORT' => 'ASC'],
        [
            'IBLOCK_ID' => $arParams["IBLOCK_ID"],
            'CODE' => $promoteSectionCodes,
            'GLOBAL_ACTIVE' => 'Y',
        ],
        false,
        ['ID','NAME','CODE','SORT','PICTURE','SECTION_PAGE_URL']
    );
    
    while($sec = $rs->GetNext()) {
    
        $sec["SECTION_PAGE_URL"] = CIBlock::ReplaceDetailUrl(
            $sec["SECTION_PAGE_URL"],
            $sec,
            false,
            'S'
        );
    
        $sec["DEPTH_LEVEL"] = 1;
        $sec["SECTIONS"] = [];
    
        $additionalSections[$sec["CODE"]] = $sec;
    }
    
    $top = array_values($arResult["SECTIONS"]);
    
    foreach ($promoteSectionCodes as $code) {
    
        if (!isset($additionalSections[$code])) continue;
    
        $new = $additionalSections[$code];
        $sort = (int)$new['SORT'];
    
        $insertIndex = count($top);
    
        foreach ($top as $i => $item) {
            $itemSort = isset($item['SORT']) ? (int)$item['SORT'] : 500;
    
            if ($itemSort > $sort) {
                $insertIndex = $i;
                break;
            }
        }
    
        array_splice($top, $insertIndex, 0, [$new]);
    }
    
    $arResult["SECTIONS"] = $top;

    список разделов


    4. Важные моменты

    • Решение не изменяет структуру инфоблока
    • URL остаются вложенными (SEO не страдает)
    • Сортировка берется из реального поля SORT
    • Работает отдельно для меню и отдельно для списка разделов

    5. Итог

    Таким образом можно гибко управлять отображением каталога без изменения структуры данных:

    • в меню — через модификацию массива
    • в списке разделов — через догрузку элементов

    Это универсальный подход для Aspro Max и Aspro Next.

    Комментарии
    Name
    Email
    Phone
    Ваше имя
    Ваш email
    Оставить комментарий
    Нажмите для звонка
    +7 (499) 341-00-19