Добро пожаловать на сайт <БагБД>, где вы можете задавать вопросы о программировании и разработке на Битрикс и Битрикс24, и получать быстрые и квалифицированные ответы от профессионалов!

Собственный компонент, выборка разделов и элементов инфоблока

00 голосов
6
Добрый день.

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

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

В пользовательской части решено было создать собственный компонент. Его логика довольно проста - загрузить список разделов и файлов. Дополнительно для компонента добавил настройки глубины выборки дерева, показ количества закрепленных файлов за документом и т.п. (это к слову).

Как сделан компонент. Выбирается список разделов CIBlockSection::GetList с сортировкой 'LEFT_MARGIN' => 'ASC'. Далее в цикле для каждого раздела запрашивается список прикрепленных элементов CIBlockElement::GetList с указанием родителя и доп. параметрами и для каждого выбранного элемента запрашивается информация по прикрепленному файлу CFile::GetByID (дело в том, что для каждого выбранного элемента в поле PROPERTY_имя_параметра_с_файлом возвращается только ID прикрепленного файла). Итого получается довольно много запросов. На мой взгляд, этот список можно собрать куда более эффективно в один/пару запросов. Но это если писать выборку от руки.

Подскажите, пожалуйста, есть ли возможность собрать данное "дерево", используя реализованный функционал Bitrix, более рациональным/эффективных способом? Или же я неправильно изначально реализовал принцип хранения / процедуру выборки данных?

К слову, дополнительно я прикрутил стандартное кэширование компонентов, что, теоретически, должно помочь.
спросил 18 Сен, 13 от Kutsumi (120 баллов)

6 Ответы

00 голосов
Пользуйте CFile::GetList

Цитата

// для свойств типа F получаем массивы, описывающие файлы
// разработчики признали баг в API, в следующий апдейт должны починить

// конвертируем массив в строку
$strFileID = '';
foreach($arFilesID as $fileID)
{
$strFileID .= $fileID . ',';
}
// отрезаем последнюю запятую
$strFileID = substr($strFileID,0, strlen($strFileID)-1);
// в фильтр добавляем плейсхолдер
$arFilesID = array("@ID" => $strFileID);

// делаем запрос
$arResultFiles = array();
$rcsFiles = CFile::GetList(false, $arFilesID, false);
while($arFile = $rcsFiles->GetNext())
{
// делаем реврайтинг и создаём поле SRC
// в поле SRC хранится путь к ресурсу
$src = "/".(COption::GetOptionString("main", "upload_dir", "upload"))."/".$arFile["SUBDIR"]."/".$arFile["FILE_NAME"];
$src = str_replace("//","/",$src);
if(defined("BX_IMG_SERVER"))
$src = BX_IMG_SERVER.$src;
$arFile = $arFile + Array("SRC" => $src);

$arResultFiles[$arFile['ID']] = $arFile;
}
ответил 22 Сен, 13 от ledyNEXUS (420 баллов)
00 голосов
Логика простая:
1 - собрать все айдишники файлов
2 - седелать запрос
3 - развесить результаты

P.S. Писалось помнится для довольно специфичной вещи поэтому можно в вашем случае сделать проще и лаколничнее.
ответил 21 Дек, 13 от ledyNEXUS (420 баллов)
00 голосов
Максим Месилов, получается, можно сэкономить только на выборке всех прикрепленных файлов? Хотя, и это вполне даже неплохо. Спасибо, я чего-то упустил этот момент...

К слову, метод COption::GetOptionString кэширует возвращаемые данные (при условии идентичности входящих параметров) или нет? Я так же использовал COption::GetOptionString("main", "upload_dir", "upload"), только результат помещал в static переменную, чтобы только при первом обращении к функции загрузки файлов определялся каталог.
ответил 06 Апр, 14 от Kutsumi (120 баллов)
00 голосов
Так вот не скажу. По идее должен он там это дело кешировать и кидать в глобалс к примеру или ещё как.

Открываете bitrix\modules\main\classes\general\option.php и смотрите соответствующий метод.
ответил 30 Июль, 14 от ledyNEXUS (420 баллов)
00 голосов
Тако оно и есть судя по коду. Кешируется всё.
ответил 02 Дек, 14 от ledyNEXUS (420 баллов)
00 голосов
Код
Как сделан компонент. Выбирается список разделов CIBlockSection::GetList с сортировкой 'LEFT_MARGIN' => 'ASC'. Далее в цикле для каждого раздела запрашивается список прикрепленных элементов 



Если это всё вам нужно на одной странице, то можете попробовать выбрать одним запросом сначала все секции.

Потом вторым все элементы ИБ, находящиеся или в родительском или подчинённых узлах. Всё дерево получается.

Для каждого элемента там будет указан ID секции к которой он пренадлежит если он к одной секции привязан.

Потом обойдите этот рекордсет и соберите айдишники файлов и сделайте запрос к таблице файлов.

В шаблоне уже обходите к примеру массив с секциями и одновременно выбирайте на каждой итерации из массивов ИБ и Файлов нужные элементы.


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

Думаю тут завсегдатаи ещё всякого полезного насоветуют.
ответил 26 Март, 15 от ledyNEXUS (420 баллов)

Похожие вопросы

0 голосов
3 ответов
0 голосов
1 ответ
спросил 17 Июль, 13 от Asteria (1,840 баллов)
0 голосов
1 ответ
0 голосов
4 ответов
спросил 28 Ноя, 13 от Sturmwind (300 баллов)