Возможно, задача, решение которой описано в этой статье покажется очень специфичной, но порой такие задачи возникают, а решить их с помощью стандартных компонентов системы не удается. Приходится искать нестандартное решение. Задача связана с выводом элементов инфоблока на странице сайта, но не все так просто: существует список компаний, у некоторых из них есть дочерние компании. У каждой компании из списка есть описание. Нужно вывести список названий компаний на страницу сайта в виде таблицы, состоящей из 2 ячеек в каждой строке. В первой ячейке будут находиться головные компании, а также компании, не имеющие дочерних компаний, во второй ячейке будут сгруппированы дочерние компании. В случае отсутствия дочерних компаний – ячейка будет пуста.
Как обычно, все действия проводятся мной над демо-версией сайта. При установке системы на локальный веб-сервер я выбираю вариант сайта под названием «Решение для разработчиков».
Все компании из списка будут являться элементами инфоблока «Компании». Дочерние компании будут привязаны к своим «родителям» через значение свойства инфоблока с названием «Родитель». Сначала создадим тип инфоблока (companies
) и сам инфоблок (ID 14
), а также добавим в него свойство «Родитель» (PARENT_COMP
). Тип свойства – «привязка к элементам». Не забудьте установить права доступа на чтение для всех пользователей.
Затем наполним его тестовыми данными и сделаем привязку дочерних компаний к своим «родителям». Так как все описания всех компаний (независимо, дочерняя компания или нет) находятся в одном инфоблоке, элементы будут связаны внутри одного инфоблока – это будет особенностью решения этой задачи.
Создадим новую страницу, разместим на ней компонент bitrix:catalog.section, который будет выводить список. Страницу можно разместить в корне сайта и назвать, например, test_links.php. После размещения компонента, скопируем его шаблон и назовем его «el_links
».
Кроме того, в настройках компонента в разделе «Внешний вид» → «Свойства» выберем имя свойства в котором хранится привязка (PARENT_COMP
). Теперь изменим результаты работы компонента в файле result_modifier.php и кастомизируем его шаблон. Создадим файл result_modifier.php и разместим в нем следующий код:
PHP
<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
$elInSect = array();
foreach($arResult["ITEMS"] as $arrkey => $arItem){
// если у заказчика нет описания – пропускаем
if(strlen($arItem["PREVIEW_TEXT"]) == 0) continue;
// ИД родительского элемента (компании)
$parentSectID = $arItem["PROPERTIES"]["PARENT_COMP"]["VALUE"];
// получаем название и код компании родителя, если у элемента есть родитель
if($parentSectID !== ""){
$res = CIBlockElement::GetByID($parentSectID);
while($ar_res = $res -> GetNext()){
$parentSectName = $ar_res["NAME"];
$parentSectCode = $ar_res["CODE"];
}
}
// если у элемента нет родителя, то записываем данные его самого
else{
$parentSectName = $arItem["NAME"];
$parentSectCode = $arItem["CODE"];
}
// сохраняем имя и код в массив, если у элемента ЕСТЬ родитель
if(!empty($parentSectID) && !array_key_exists($parentSectID, $elInSect)){
$elInSect[$parentSectID]["NAME"] = $parentSectName;
$elInSect[$parentSectID]["CODE"] = $parentSectCode;
}
// сохраняем имя и код в массив, если у элемента НЕТ родителя
else if(empty($parentSectID) && !array_key_exists($parentSectID, $elInSect)){
$elInSect[$arItem["ID"]]["NAME"] = $parentSectName;
$elInSect[$arItem["ID"]]["CODE"] = $parentSectCode;
}
if(!empty($parentSectID) && array_key_exists($parentSectID, $elInSect)){
$elInSect[$parentSectID]["ELEMENTS"][$arItem["ID"]]["NAME"] = $arItem["NAME"];
$elInSect[$parentSectID]["ELEMENTS"][$arItem["ID"]]["CODE"] = $arItem["CODE"];
}
}
$arResult["CONTENTS"] = $elInSect;
?>
Этот код сгруппирует дочерние компании и поместит их в массив с описанием головной компании. Чтобы проверить, правильно ли все сделано, выведем содержимое массива $elInSect
с помощью функции print_r()
. Должна получиться такая картина:
Если всё верно, то можно перейти к кастомизации шаблона. Замысел следующий: сначала выводится таблица с наименованиями компаний (по шаблону, описанному в начале статьи), а затем список всех компаний с их описаниями. У каждого наименования компании будет идентификатор, на который будет вести гиперссылка из списка.
PHP
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
<?if(count($arResult["CONTENTS"]) > 0):?>
<table class="pr_orders" style="border-collapse: collapse;">
<?foreach($arResult["CONTENTS"] as $arLinks):?>
<tr>
<td class="tdtitle" style="border-image: none;">
<a href="#<?=$arLinks["CODE"]?>"><?=$arLinks["NAME"]?></a>
</td>
<?if(isset($arLinks["ELEMENTS"])):?>
<td>
<?foreach($arLinks["ELEMENTS"] as $arSecLink):?>
<a href="#<?=$arSecLink["CODE"]?>"><?=$arSecLink["NAME"]?></a><br />
<?endforeach;?>
</td>
<?else:?>
<td></td>
<?endif;?>
</tr>
<?endforeach;?>
</table>
<?endif;?>
<?foreach($arResult["ITEMS"] as $cell=>$arElement):?>
<?if($arElement["PREVIEW_TEXT"] == "") continue;?>
<div>
<p id="<?=$arElement["CODE"]?>" class="title2"><?=$arElement["NAME"]?></p>
<?if(is_array($arElement["PREVIEW_PICTURE"])):?>
<img src="/<?=$arElement["PREVIEW_PICTURE"]["SRC"]?>" style="float:left;margin-right:5px;" />
<?endif;?>
<?=$arElement["PREVIEW_TEXT"]?>
<div style="height:1px; clear:both;"></div>
</div>
<?endforeach;?>
Я упростил шаблон, убрав из него все лишнее для решения данной задачи, поэтому содержимое файла сильно сократилось. Осталось только немного украсить получившийся список, написав несколько правил CSS. В итоге получим страничку со списком компаний. Например, это может быть список заказчиков.
Внешний вид получившего списка близок к тому, который задумывался в начале статьи, так что можно считать задачу выполненной.