R
R
Roman Lee2021-07-22 10:15:25
1C-Bitrix
Roman Lee, 2021-07-22 10:15:25

How to display certain sections and nested elements in the form of a tree from the infoblock?

The main task: it is necessary to remove certain sections and nested elements from the infoblock, with a minimum number of queries to the database. Important - one element can consist of several sections.

The output should be a structure:
Section 1

  • Document 1
  • Document 1

Section N
  • Document N
  • Document N


Below is the current implementation code.
The disadvantage of this code is that too many database queries are performed. How can it be optimized?
The $arResult array must contain the names of sections and elements.
<?  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 
?>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
T
tgarl, 2021-07-22
@tgarl

1. When selecting elements, you forgot to put a filter on the necessary sections, so everything is taken from others too, i.e. superfluous (by adding a filter you will avoid doing separate checks)

$arFilter = array("IBLOCK_ID" => $IBLOCK_ID, "ACTIVE_DATE" => "Y", "ACTIVE" => "Y", "SECTION_ID" => $idSections, "INCLUDE_SUBSECTIONS" => "Y",);

2. form the required array at the foreach level ($arResult["ITEMS"] as $key => $arItem) , then you will avoid 3 nested loops (3 nested loops are very heavy, try to avoid such constructions)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question