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

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

Среда, 31 октября 2012 17:23

Список элементов инфоблока с названиями разделов в качестве заголовков

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

Как известно в «1С-Битрикс» нет стандартного компонента, который бы выводил элементы инфоблока, расположенные в разделах, таким образом, чтобы название раздела было заголовком списка элементов из этого раздела. Однажды мне понадобилось вывести список проектов одной компании на страницу сайта описанным выше образом. Я нашел 2 способа решения этой задачи, о которых расскажу в этой статье.

Решать эту задачу я буду на демо-сайте CMS «1С-Битрикс. Управление сайтом» редакция «Стандарт». При установке демо-версии сайта и выбора типа решения для демонстрации, нужно выбрать версию для разработчиков. В версии для разработчиков существует инфоблок «Книги». Его элементы распределены по разделам. С ним я и буду работать.

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

Сначала, как обычно подготовительный этап: нужно создать новое свойство страницы (Настройки → Настройки продукта → Настройки модулей → Управление структурой). Оно понадобится в случае, когда элементы, которые нужно будет вывести на странице, находятся в подразделах какого-либо раздела. Назову этот раздел – «разделом первого уровня», хотя необязательно, что он будет находиться в дереве разделов инфоблока на первом уровне. В этом свойстве будет храниться идентификатор раздела первого уровня, в котором находятся разделы с элементами. Назовем его sect_id.

Добавляем свойство страницы

Также нужно создать 2 пустые страницы. Пусть они будут располагаться в папке test, расположенной в корне демо-сайта. Назовем первую list-1.php, а вторую list-2.php.

Создаем 2 пустые страницы

Первый способ – используем Bitrix Framework

Открываем страницу list-1.php и присваиваем созданному свойству sect_id значение 13 (в демо-версии сайта – это раздел под названием «Наука и образование»).

PHP

<? $APPLICATION->SetPageProperty("sect_id", "13"); ?>

Я решил организовать код скрипта в виде функции под названием MakeElementsTree, для его повторного использования. Будет правильно размещать все написанные вами функции в файле \bitrix\php_interface\init.php. Вот код функции:

PHP

<?
function MakeElementsTree(){
  global $APPLICATION;
   if(!CModule::IncludeModule("iblock")){
     echo "Не подключается модуль инфоблоки";
   }
  // Идентификатор раздела 
    $eltype = $APPLICATION->GetPageProperty("sect_id");
     if (!empty($eltype))
	{
         //ID инфоблока
 	 $res = CIBlockSection::GetByID($eltype);
         if($ar_res = $res->GetNext()) $parentIBlockID = $ar_res['IBLOCK_ID'];
         $arFilter=array(
		"IBLOCK_ID" => $parentIBlockID,
		"SECTION_ID" => $eltype,
	  );
	  $ar_result=Array();
          $arProj = CIBlockSection::GetList(array("SORT"=>"ASC"),$arFilter,false);
	  while($projRes = $arProj->GetNextElement())
	   {
	    $arFields = $projRes->GetFields();
	    $ar_result[$arFields["ID"]]["NAME"] = $arFields["NAME"];
           }	
       	     foreach($ar_result as $arrkey => $arrvalue){
	       $arProjElem = CIBlockElement::GetList(array(),array("SECTION_ID"=>$arrkey),false);
		 while($projResElem = $arProjElem->GetNextElement())
		  {
		   $arElemFields = $projResElem->GetFields();
		   $arSelFlds["NAME"] = $arElemFields["NAME"];
		   $arSelFlds["PREVIEW_TEXT"] = $arElemFields["PREVIEW_TEXT"];
		   $arSelFlds["DETAIL_PAGE_URL"] = $arElemFields["DETAIL_PAGE_URL"];
		   $arSelFlds["DETAIL_TEXT_SIZE"] = strlen($arElemFields["DETAIL_TEXT"]);
		   $ar_result[$arrkey]["ITEMS"][] = $arSelFlds;
		  }
		}
	     foreach($ar_result as $key => $arrValues)
	      {
	       echo "<h4>".$arrValues["NAME"]."</h4>";
	       if(is_array($arrValues["ITEMS"]) && count($arrValues["ITEMS"]) > 0)
		 {
		   echo "<ul style=\"margin-bottom:10px;\">";
		      foreach ($arrValues["ITEMS"] as $arrItem)
                       {
			echo "<li class=\"gvert\">";
			  if($arrItem["DETAIL_TEXT_SIZE"] > 0)
		   	    {
			     echo "<a href=\"".$arrItem["DETAIL_PAGE_URL"]."\" 
        style=\"font-weight:bold;\" >".$arrItem["NAME"]."</a><br />";
			    }
		  	   else
			    {
			     echo "<span style=\"font-weight:bold;\">".
        $arrItem["NAME"]."</span><br />";
			    }
	if(strlen($arrItem["PREVIEW_TEXT"]) > 0){
	   echo "<span>".$arrItem["PREVIEW_TEXT"]."</span>"; 
	 }
        echo "</li>";				
       }		
     echo "</ul>";
    }
   }	
  }
 else{
    showError("В свойствах страницы не указан ID раздела с элементами");
  }
} //end MakeElementsTree
?>

Внутри функции сначала проверяем, установлен ли в системе модуль «Информационные блоки». Если да – подключаем его. Теперь нам доступны все методы и функции класса. Далее сохраняем в переменной $eltype значение свойства sect_id страницы, установленное выше. Напомню, что это код раздела первого уровня, в нем находятся разделы с элементами, которые мы будем выводить на нашей странице. По коду раздела определяем код инфоблока и помещаем эти данные в массив $arFilter, который будет являться фильтром для выборки разделов (находящихся внутри раздела первого уровня).

Создаем пустой массив с именем $ar_result. Он будет «основным» в нашем скрипте, - то есть в него будет сохраняться вся информация о разделах и элементах, которые потом будут выведены на страницу сайта.

Получаем данные о разделах и сохраняем их в виде массивов в основной массив $ar_result. Ключами элементов массива будут идентификаторы подразделов с элементами. Внутри каждого массива будет элемент “NAME” с названием раздела.

Массив разделов

Теперь обходим в цикле получившийся массив и дополняем его информацией об элементах из разделов. Используем для этого метод CIBlockElement::GetList, передаем ему в виде фильтра идентификаторы разделов. Далее получаем значения полей элементов CIBlockResult::GetNextElement - сохраняем необходимые данные в массиве. Массивы со значениями полей элементов, помещаем в массив $ar_result[код_раздела][“ITEMS”].

В массив добавлены элементы

Массив $ar_result заполнен информацией как было задумано в начале. Теперь можно вывести на страницу информацию из него. За это отвечает оставшаяся часть кода. Результат работы скрипта можно увидеть на рисунке:

Результаты работы скрипта

Внешний вид списка можно настроить при помощи CSS или поправил ту часть скрипта, которая отвечает за вывод элементов массива $ar_result.

Небольшое ограничение: при указании раздела первого уровня, элементы, находящиеся в нем, в списке отображаться не будут, будут отображаться только элементы из подразделов раздела первого уровня. Я немного расширил скрипт так, что элементы внутри раздела первого уровня тоже отображаются в списке. Расширенная версия находится в файле list-1f.php.

С первым способом закончили, теперь можно перейти ко второму.

Второй способ – используем несколько стандартных компонентов и настраиваем их шаблоны.

Второй способ формирования списка элементов с заголовками из названия их разделов, заключается в использовании стандартных компонентов системы catalog.section и catalog.section.list, а именно в кастомизации шаблонов этих компонентов.

Открываем страницу list-2.php и присваиваем созданному свойству sect_id значение 13 (в демо-версии сайта – это раздел под названием «Наука и образование»).

PHP

<? 
   $APPLICATION->SetPageProperty("sect_id", "13");
   $sect_id = $APPLICATION->GetPageProperty("sect_id");
?>

Затем размещаем на странице код вызова компонента catalog.section.list со следующими параметрами: тип инфоблока – “books”, инфоблок – «Книги[6]», в поле «ID раздела» - указываем имя переменной $sect_id, в которой хранится идентификатор раздела первого уровня.

Параметры компонента catalog.section.list

Далее нужно скопировать шаблон компонента в папку текущего шаблона. В архиве, который можно скачать по ссылке в конце этой статьи в папке templates находятся файлы шаблонов обоих компонентов. Скопируем шаблоны компонентов catalog.section.list и catalog.section в папку шаблона сайта. На демо-сайте это будет папка /bitrix/templates/books/components/bitrix/. В нее нужно скопировать обе папки и выбрать этот шаблон “projects” в настройках компонента на странице list-2.php.

Выбираем шаблон компонента catalog.section.list

Этот шаблон изменен таким образом, что если внутри раздела первого уровня нет дочерних разделов, то выводится список элементов, а если разделы существуют, то они обходятся в цикле и из них извлекаются дочерние элементы. В любом из перечисленных случаев элементы списка выводятся на страницу с помощью компонента catalog.section, вызов которого размещен в файле шаблона. В коде вызова этого компонента (при работе с демо-версией сайта) нужно указать следующие параметры:

PHP

…
<?if(count($arResult["SECTIONS"]) == 0):?>
…
"IBLOCK_TYPE" => "books",
"IBLOCK_ID" => "6",
"SECTION_ID" => $sect_id,
…
<?else:?>
…
"IBLOCK_TYPE" => "books",
"IBLOCK_ID" => "6",
"SECTION_ID" => $arSection["ID"],

Это нужно сделать в обоих блоках условной конструкции.

Шаблон компонента catalog.section также настроен для вывода списка в определенном виде.

PHP

<?
  if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
  <ul style="margin-bottom:10px;">
    <?foreach($arResult["ITEMS"] as $cell=>$arElement):?>
	<li>
	<?if(strlen($arElement["DETAIL_TEXT"]) > 0):?>
	  <a href="/<?=$arElement["DETAIL_PAGE_URL"]?>" 
           style="font-weight:bold;">
           <?=$arElement["NAME"]?></a><br />
		<?else:?>
	<span style="font-weight:bold;">
         <?=$arElement["NAME"]?></span><br />
		<?endif;?>
		<?if(strlen($arElement["PREVIEW_TEXT"]) > 0):?>
			<span><?=$arElement["PREVIEW_TEXT"]?></span>
		<?endif?>
	</li>
  <?endforeach; // foreach($arResult["ITEMS"] as $arElement):?>
</ul>

Поэтому внешний вид обеих страниц будет одинаковым. Это можно заметить, если посмотреть на оба скриншота страниц.

Результат работы компонентов

На этом завершаю свою статью, задача успешно выполнена двумя способами. Какой из них более удобный выбирать вам, главное чтобы он был полезен вам при решении подобной задачи.

Скачать архив с результатами работы

Прочитано 26309 раз
Добавить комментарий

Комментарии   

 
+1 # Евгений 31.08.2013 18:19
Таким же образом нужно сделать чтобы выводились не элементы раздела а его подразделы, не подскажите как?
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 31.08.2013 22:34
В этом случае вам скорее всего нужно использовать рекурсию, так как способа получения списка вложенных разделов у метода CIBlockSection::GetList() нет. Также обратите внимание на метод CIBlockSection::GetCount().
Ответить | Ответить с цитатой | Цитировать
 
 
+1 # Иван Зыков 15.01.2015 11:27
Спасибо, хорошая и полезная статья! У меня вопрос: а что нужно изменить, чтобы выводить подразделы и элементы не выбранного раздела, а всего инфоблока?
Ответить | Ответить с цитатой | Цитировать
 
 
+1 # Матвей 20.01.2015 14:10
Если я вас правильно понял, то можно воспользоваться стандартными компонентами catalog.section.list и news.list: расположить их на странице вместе (одни под другим) и настроить.
Ответить | Ответить с цитатой | Цитировать
 
 
+1 # Кирил 19.01.2016 10:29
Спасибо тебе большое
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 19.01.2016 10:56
Пожалуйста, Кирилл!
Ответить | Ответить с цитатой | Цитировать
 
Мои услуги

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

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

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

Скачать

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