Как вывести из инфоблока определенные разделы и вложенные элементы в виде дерева?

Основная задача: необходимо вывести из инфоблока определенные разделы и вложенные элементы, с минимальным количеством запросов к БД. Важно - один элемент может состоять в нескольких разделах.

На выходе должна получится структура:
Раздел 1
  • Документ 1
  • Документ 1

Раздел N
  • Документ N
  • Документ N


Ниже представлен код текущей реализации.
Минус этого кода - выполняется слишком много запросов к БД. Как его можно оптимизировать?
Массив $arResult должен содержать название разделов и элементов.
<?  CModule::IncludeModule('iblock'); //Подключаем модуль "Информационные блоки" 
    
	// Параметры
	$IBLOCK_ID = 7; // ID ифноблока
	$idSections = array(104,105,106); // ID разделов


    // Формируем список разделов по фильтру
    $dbResSect = CIBlockSection::GetList(
        array("SORT" => 'asc'), // Параметры сортировки
        array(
            "IBLOCK_ID" => $IBLOCK_ID, // ID инфоблока
            "ID" => $idSections, // Массив разделов
        ),
        false,
        array("ID", "NAME", "UF_ITEMPROP") // Выбираем необходимые поля разделов.
    );

    // Получаем разделы и собираем их в массив
    while ($sectRes = $dbResSect->GetNext()) {
        $arSections[] = $sectRes;
    }


	// Формируем массив элементов по фильтру
	$arResult = [];
	$arSelect = Array(
		"ID",
		"NAME",
		"IBLOCK_ID",
		"IBLOCK_SECTION_ID",
		"PROPERTY_FILE", 
		"PROPERTY_ITEMPROP",
	);
	$arFilter = array("IBLOCK_ID" => $IBLOCK_ID, "ACTIVE_DATE" => "Y", "ACTIVE" => "Y");
	$res = CIBlockElement::GetList(array("SORT" => "ASC"), $arFilter, false, array("nPageSize" => 100), $arSelect);
	while ($el = $res->Fetch()) {
		$arResult["ITEMS"][] = $el;
	}


    // Находим все разделы элемента и собираем их в массив
    foreach ($arResult["ITEMS"] as $key => $arItem) {
        $ElementId = $arItem['ID'];
        $db_groups = CIBlockElement::GetElementGroups($ElementId, true);
        $res = [];
        while ($ar_group = $db_groups->Fetch()) {
            $res[] = $ar_group["ID"];
        }
        $arItem["SECTION"] = $res;
        $arSection[] = $arItem;
    }
    $arResult["ITEMS"] = $arSection;


    // Собираем  массив из разделов и элементов
    foreach ($arSections as $arSection) {
        foreach ($arResult["ITEMS"] as $key => $arItem) {
            foreach ($arItem['SECTION'] as $key => $val) {
                if ($val == $arSection['ID']) {
                    $arSection['ELEMENTS'][] = $arItem;
				}
            }
        }
        $arElementGroups[] = $arSection;
    }
    $arResult["ITEMS"] = $arElementGroups;

    // Далее распаковываем массив $arResult 
?>
  • Вопрос задан
  • 980 просмотров
Пригласить эксперта
Ответы на вопрос 1
@tgarl
1. Вы забыли при отборе элементов поставить фильтр на нужные разделы, поэтому берутся все и из других тоже, т.е. лишние (добавив фильтр вы избежите делать отдельные проверки)
$arFilter = array("IBLOCK_ID" => $IBLOCK_ID, "ACTIVE_DATE" => "Y", "ACTIVE" => "Y", "SECTION_ID" => $idSections, "INCLUDE_SUBSECTIONS" => "Y",);

2. формируйте нужный массив на уровне foreach ($arResult["ITEMS"] as $key => $arItem) , тогда вы избежите 3 вложенных циклов(3 вложенных цикла очень сильно нагружают, старайтесь такие конструкции избегать)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы