Матвей Земсков

Заметки веб-мастера

Пятница, 04 января 2013 16:17

Сложная группировка элементов инфоблока и вывод на страницу сайта.

Оцените материал
(3 голосов)

В предыдущей статье я описывал способ группировки элементов инфоблока на сайте под управлением «1С-Битрикс». Он заключался в следующем: элементы группировались на основе привязки к другим элементам того же инфоблока. Чтобы было понятней – таким образом можно организовать список компании (например, заказчиков) в случае, если у этих компаний есть дочерние компании. Список получился многоуровневым: на первом уровне – головные компании, на втором – дочерние. Сейчас немного усложним задачу и добавим еще 2 условия: во-первых, элементы будут находиться в разделах, «связанные» элементы, по которым будет проводиться группировка будут находиться в другом инфоблоке и их значение может быть множественным, т.е. «привязка» может содержать несколько элементов.

Так как все действия я, как обычно, буду проводить над демо-версией системы (решение «для разработчиков»), объясню все указанное выше более понятным языком, так сказать, на практическом примере. В демо-версии системы есть каталог книг. Книги в нем хранятся в одном инфоблоке («Каталог книг» → «Книги») и распределены по разделам, а авторы в другом инфоблоке («Каталог книг» → «Авторы»). Авторы привязаны к книгам через одно из свойств инфоблока с книгами. Также у книги может быть несколько авторов. Задача состоит в следующем: нужно вывести список книг с указанием разделов, таким образом, чтобы книги были сгруппированы не только по разделам, а еще и по авторам, как указано на схеме.

Схема будущего списка

Задача получилась настолько нестандартная, что применением стандартных компонентов системы не решается, поэтому нам на помощь приходит Bitrix Framework. После установки демо-версии особой подготовительной работы проводить не нужно, нужно только создать новую страницу, например, в корневой папке сайта и можно начинать писать код. Код будет оформлен в виде функции с именем MakeElementsTree, которой будут передаваться несколько параметров: ИД инфоблока с книгами, имя свойства, в котором хранится связь с автором (или авторами). Также в функцию может передаваться ИД раздела, в случае если книги будут выбираться из определенного раздела инфоблока, а не из корневого.

Функция MakeElementsTree будет формировать массив с книгами, в соответствии с условиями задачи и выводить на страницу. Работу функции можно разделить на 3 части: первая часть - выборка данных из корневого радела и сохранение в массив, вторая – выборка данных из разделов, находящихся внутри корневого раздела и сохранение в массив, третья - вывод данных из массива на страницу.

PHP

function MakeElementsTree($prntIBid,$lnkPropName,$eltype = null){
    if(!CModule::IncludeModule("iblock")){
	echo "не подключается модуль инфоблоки";
    }
    // если номер раздела передан в функцию, добавляем его в фильтр
		if (isset($eltype) && $eltype != '')
		   {
			$arFilter=array(
				"IBLOCK_ID" => $prntIBid,
				"SECTION_ID" => $eltype,
				"ACTIVE" => "Y",
				);
		 }
  	              else{
		  // если нет выбираем разделы верхнего уровня
		$arFilter=array(
			"IBLOCK_ID" => $prntIBid,
			"DEPTH_LEVEL" => 1,
			"ACTIVE" => "Y",
			);
		 }
	   $ar_result=Array();
	  // ВЫБИРАЕМ ЭЛЕМЕНТЫ ИЗ КОРНЕВОГО РАЗДЕЛА
	    $arFilterRoot = array(
			"IBLOCK_ID" => $prntIBid,
			"SECTION_ID" => "",
			"ACTIVE" => "Y",
			);
	$arProjRootElem = CIBlockElement::GetList(array("SORT"=>"ASC"),$arFilterRoot,false);
	while($projResElem = $arProjRootElem->GetNextElement()){
		$arElemFld = $projResElem->GetFields();
		$arElemProp = $projResElem->GetProperties();
		$arSelPropRoot[$arElemFld["ID"]] = $arElemProp[$lnkPropName]["VALUE"];
   	 }
	foreach($arSelPropRoot as $propkey => $propval){
  	    //если значение свойства где хранится привязка множественное - формируем ключ и объединяем значения в одну строку
         	   if(count($propval) > 1){
                	$rpppval = "";
		$rpppres = "";
		foreach($propval as $rppkey => $rppval){
                	$arLnkRootElem = CIBlockElement::GetByID($rppval);
			if($arLnkRootElem_res = $arLnkRootElem->GetNext()){
				$rpppval .= $rppval;
				$rpppres .= $arLnkRootElem_res["NAME"]." ";
			}
		}
		$ar_result_root["CUST_ITEMS"][$rpppval]["NAME"] = $rpppres;
		$arElemVal = CIBlockElement::GetByID($propkey);
		if($arLnkRootElem_res = $arElemVal->GetNext()){
  		     $ar_result_root["CUST_ITEMS"][$rpppval]["ELEM"][$arLnkRootElem_res["ID"]]["NAME"]= $arLnkRootElem_res["NAME"];
                 $ar_result_root["CUST_ITEMS"][$rpppval]["ELEM"][$arLnkRootElem_res["ID"]]["PREVIEW_TEXT"] = $arLnkRootElem_res["PREVIEW_TEXT"];
                 $ar_result_root["CUST_ITEMS"][$rpppval]["ELEM"][$arLnkRootElem_res["ID"]]["DETAIL_TEXT"] = $arLnkRootElem_res["DETAIL_TEXT"];
                 $ar_result_root["CUST_ITEMS"][$rpppval]["ELEM"][$arLnkRootElem_res["ID"]]["D_TXT_LENGTH"] = strlen($arRootLnkElem_res["DETAIL_TEXT"]);
                 $ar_result_root["CUST_ITEMS"][$rpppval]["ELEM"][$arLnkRootElem_res["ID"]]["DETAIL_PAGE_URL"] = $arRootLnkElem_res["DETAIL_PAGE_URL"];
		}
  	   }
	// иначе просто получаем ключ и значение.
	else{
	    foreach($propval as $rppkey => $rppval){
		$arLnkRootElem = CIBlockElement::GetByID($rppval);
		if($arLnkRootElem_res = $arLnkRootElem->GetNext()){
		      $ar_result_root["CUST_ITEMS"][$rppval]["NAME"] = $arLnkRootElem_res["NAME"];								
		}
	 }
	$arElemVal = CIBlockElement::GetByID($propkey);
	if($arLnkRootElem_res = $arElemVal->GetNext()){
		$ar_result_root["CUST_ITEMS"][$rppval]["ELEM"][$arLnkRootElem_res["ID"]]["NAME"]= $arLnkRootElem_res["NAME"];
            $ar_result_root["CUST_ITEMS"][$rppval]["ELEM"][$arLnkRootElem_res["ID"]]["PREVIEW_TEXT"] = $arLnkRootElem_res["PREVIEW_TEXT"];
            $ar_result_root["CUST_ITEMS"][$rppval]["ELEM"][$arLnkRootElem_res["ID"]]["DETAIL_TEXT"] = $arLnkRootElem_res["DETAIL_TEXT"];
            $ar_result_root["CUST_ITEMS"][$rppval]["ELEM"][$arLnkRootElem_res["ID"]]["D_TXT_LENGTH"] = strlen($arRootLnkElem_res["DETAIL_TEXT"]);
            $ar_result_root["CUST_ITEMS"][$rppval]["ELEM"][$arLnkRootElem_res["ID"]]["DETAIL_PAGE_URL"] = $arRootLnkElem_res["DETAIL_PAGE_URL"];
	}
        }
       $ar_result_root["CUST_SUBSECT"]= $arSelPropRoot;
       unset($arSelPropRoot);
    }	 		
  // ВЫБИРАЕМ ЭЛЕМЕНТЫ ИЗ РАЗДЕЛОВ
$arProj = CIBlockSection::GetList(array("SORT"=>"ASC"),$arFilter,false);
     while($projRes = $arProj->GetNextElement())
       {
	$arFields = $projRes->GetFields();
	$ar_result[$arFields["ID"]]["NAME"] = $arFields["NAME"];
	$ar_result[$arFields["ID"]]["CODE"] = $arFields["CODE"];
      }			
     // узнаем ИД связанных элементов из другого инфоблока
     foreach($ar_result as $arrkey => $arrvalue){
	   $arProjElem = CIBlockElement::GetList(array("SORT"=>"ASC"),array("SECTION_ID"=>$arrkey),false);
 	    while($projResElem = $arProjElem->GetNextElement())
	       {
 		$arElemFld = $projResElem->GetFields();
		$arElemProp = $projResElem->GetProperties();
		$arSelProp[$arElemFld["ID"]] = $arElemProp[$lnkPropName]["VALUE"];
	      }
	   foreach($arSelProp as $propkey => $propval){
   		//если значение свойства где хранится привязка множественное - формируем ключ и объединяем значения в одну строку
		if(count($propval > 1)){
		         $pppval = "";
 	                         $pppres = "";
		         foreach($propval as $ppkey => $ppval){
			  $arLnkElem = CIBlockElement::GetByID($ppval);
				if($arLnkElem_res = $arLnkElem->GetNext()){
					$pppval .= $ppval;
					$pppres .= $arLnkElem_res["NAME"]." ";
				}							 
			}
		    $ar_result[$arrkey]["CUST_ITEMS"][$pppval]["NAME"] = $pppres;
		    $arElemVal = CIBlockElement::GetByID($propkey);
		     if($arLnkElem_res = $arElemVal->GetNext()){
			$ar_result[$arrkey]["CUST_ITEMS"][$pppval]["ELEM"][$arLnkElem_res["ID"]]["NAME"]= $arLnkElem_res["NAME"];
                  $ar_result[$arrkey]["CUST_ITEMS"][$pppval]["ELEM"][$arLnkElem_res["ID"]]["PREVIEW_TEXT"] = $arLnkElem_res["PREVIEW_TEXT"];
                  $ar_result[$arrkey]["CUST_ITEMS"][$pppval]["ELEM"][$arLnkElem_res["ID"]]["DETAIL_TEXT"] = $arLnkElem_res["DETAIL_TEXT"];
                  $ar_result[$arrkey]["CUST_ITEMS"][$pppval]["ELEM"][$arLnkElem_res["ID"]]["D_TXT_LENGTH"] = strlen($arLnkElem_res["DETAIL_TEXT"]);
                  $ar_result[$arrkey]["CUST_ITEMS"][$pppval]["ELEM"][$arLnkElem_res["ID"]]["DETAIL_PAGE_URL"] = $arLnkElem_res["DETAIL_PAGE_URL"];
                 }							
       }
	// иначе просто получаем ключ и значение.
	else{
	    foreach($propval as $ppkey => $ppval){
		$arLnkElem = CIBlockElement::GetByID($ppval);
		if($arLnkElem_res = $arLnkElem->GetNext()){
			$ar_result[$arrkey]["CUST_ITEMS"][$ppval]["NAME"] = $arLnkElem_res["NAME"];
		}						
	}
	$arElemVal = CIBlockElement::GetByID($propkey);
	if($arLnkElem_res = $arElemVal->GetNext()){
	      $ar_result[$arrkey]["CUST_ITEMS"][$ppval]["ELEM"][$arLnkElem_res["ID"]]["NAME"]= $arLnkElem_res["NAME"];
                      $ar_result[$arrkey]["CUST_ITEMS"][$ppval]["ELEM"][$arLnkElem_res["ID"]]["PREVIEW_TEXT"] = $arLnkElem_res["PREVIEW_TEXT"];
                      $ar_result[$arrkey]["CUST_ITEMS"][$ppval]["ELEM"][$arLnkElem_res["ID"]]["DETAIL_TEXT"] = $arLnkElem_res["DETAIL_TEXT"];
                      $ar_result[$arrkey]["CUST_ITEMS"][$ppval]["ELEM"][$arLnkElem_res["ID"]]["D_TXT_LENGTH"] = strlen($arLnkElem_res["DETAIL_TEXT"]);
                      $ar_result[$arrkey]["CUST_ITEMS"][$ppval]["ELEM"][$arLnkElem_res["ID"]]["DETAIL_PAGE_URL"] = $arLnkElem_res["DETAIL_PAGE_URL"];
	}							
     }
}					
$ar_result[$arrkey]["CUST_SUBSECT"]= $arSelProp;
unset($arSelProp);
}
// ПОКАЗЫВАЕМ ЭЛЕМЕНТЫ ИЗ КОРНЕВОГО РАЗДЕЛА
	if(isset($ar_result_root) && is_array($ar_result_root["CUST_ITEMS"]) && count($ar_result_root["CUST_ITEMS"]) > 0)
	  {
	        foreach($ar_result_root ["CUST_ITEMS"] as $arr_cust_items){
		echo "<p class=\"surname2\">".$arr_cust_items["NAME"]."</p>";
		echo "<ul style=\"margin-bottom:10px;\">";
		      foreach($arr_cust_items["ELEM"] as $arrItem){
			echo "<li class=\"gvert\" style=\"margin-bottom:10px;\">";
			echo $arrItem["NAME"]; 
		                echo "</li>";
		     }
		echo "</ul>";
	       }
	  }
// ПОКАЗЫВАЕМ ЭЛЕМЕНТЫ ИЗ РАЗДЕЛОВ
	foreach($ar_result as $key => $arrValues)
	   {
	         if(is_array($arrValues["CUST_ITEMS"]) && count($arrValues["CUST_ITEMS"]) > 0)
	           {
		echo "<h3 class=\"title1\" id=\"".$arrValues["CODE"]."\">".$arrValues["NAME"]."</h3>";
		    foreach($arrValues["CUST_ITEMS"] as $arr_cust_items){
			echo "<p class=\"surname2\">".$arr_cust_items["NAME"]."</p>";
			echo "<ul style=\"margin-bottom:10px;\">";
			   foreach($arr_cust_items["ELEM"] as $arrItem){
			         echo "<li class=\"gvert\" style=\"margin-bottom:10px;\">";
			            echo $arrItem["NAME"]; 
			         echo "</li>";
			      }
		                echo "</ul>";
		   }
	            }
           } 
  } 

Функция работает следующим образом: в начале проверяется передан ли функции в качестве параметра ИД родительского раздела. В зависимости от этого формируется массив $arFilter, который участвует в процессе выборки элементов, являясь фильтром. Создается пустой массив $ar_result, в который будет помещаться информация, полученная в процессе работы функции. Сначала в массив помещается информация о разделах (ИД, название, символьный код). На основе этих данных получаем значение свойства элементов инфоблока «Книги», в котором хранится «привязка» к элементам инфоблока «Авторы». Узнаем информацию об авторе (авторах). Если у книги авторов несколько объединяем их всех в одну строку, разделяя пробелами, и также помещаем в массив $ar_result. Далее получаем информацию о книгах данного автора (авторов) и снова помещаем в массив $ar_result. В результате получается массив, показанный на скриншоте ниже.

Результат работы функции в виде массива

Далее этот массив нужно привести в удобочитаемый вид, что и делает код в третьей части функции. В данном случае список на странице будет выглядеть следующим образом:

Результат работы функции на странице сайта

На скриншоте представлен раздел «Бизнес-литература». Вы можете скачать файлы с приведенным выше кодом. Если их скопировать в папку с демо-версией сайта и не менять значения параметров при вызове функции MakeElementsTree, вы получите такой же результат, как описан в этой статье. Так вы сможете посмотреть как работает данная функция и ознакомиться с ней более детально для возможного применения на своем сайте.

Прочитано 10889 раз

Добавить комментарий


Защитный код
Обновить

Мои услуги

Предлагаю следующие услуги:

  • Верстка шаблона сайта из дизайн-макета для CMS «1С-Битрикс Управление сайтом» и CMS “Joomla”
  • Создание форм различной сложности (обратная связь, анкеты и тп) для указанных CMS
  • Настройка и кастомизация компонентов и модулей для указанных CMS
  • Доработка модулей и компонентов для указанных CMS, добавление нестандартного функционала
  • Разработка лендингов (landing-pages)

По все вопросам обращайтесь через форму обратной связи

Скачать

Предлагаю вашему вниманию: