BITRIX: получить свойства элементов любого инфоблока в любом месте и любом шаблоне
Главное: массив вида $arResult['PROPERTIES'] формируется компонентами Битрикс (например, news.detail, catalog.element) и доступен внутри их шаблонов. В «любом месте» сайта этого массива нет по умолчанию — нужно самостоятельно запросить элемент(ы) инфоблока через API D7 (CIBlockElement/CIBlockSection или ORM) и выбрать нужные свойства.
Ниже — проверенные способы, которые можно использовать в любом шаблоне, компоненте, include-области, result_modifier.php, header/footer, а также в произвольном PHP-файле при условии корректной инициализации пролога.
1) Базовый вариант: CIBlockElement::GetList + GetNextElement
Подходит, если нужен 1 элемент (например, «настройки сайта» в отдельном ИБ) или небольшая выборка.
<?php
use Bitrix\Main\Loader;
require($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main/include/prolog_before.php');
Loader::includeModule('iblock');
$iblockId = 10; // ID инфоблока
$elementId = 123; // ID элемента
$arSelect = [
'ID', 'IBLOCK_ID', 'NAME', 'CODE', 'ACTIVE', 'DETAIL_TEXT', 'DETAIL_PICTURE'
// Свойства отдельно не указываются — получим их через GetProperties()
];
$arFilter = ['IBLOCK_ID' => $iblockId, 'ID' => $elementId, 'ACTIVE' => 'Y'];
$res = CIBlockElement::GetList([], $arFilter, false, ['nTopCount' => 1], $arSelect);
if ($ob = $res->GetNextElement()) {
$fields = $ob->GetFields(); // Аналогично $arResult['FIELDS'] в компонентах
$props = $ob->GetProperties(); // Аналогично $arResult['PROPERTIES']
// Пример доступа:
// Строковое свойство
$value = $props['MY_PROP']['VALUE'];
// Файл в свойстве
if (!empty($props['FILE_PROP']['VALUE'])) {
$file = CFile::GetFileArray($props['FILE_PROP']['VALUE']);
$src = $file['SRC']; // /upload/iblock/...
}
// Множественное свойство
$values = $props['TAGS']['VALUE']; // массив значений
}Плюсы:
- Почти не требует настройки.
- Свойства приходят в удобной структуре, похожей на
$arResult['PROPERTIES'].
Минусы:
- Отдельный вызов
GetNextElement и GetPropertiesможет быть тяжелее на больших выборках. Для списков лучше использовать GetProperty.
2) Списки элементов: оптимизация по свойствам
Если нужно выбрать много элементов с конкретными свойствами, используйте выборку свойств в селекте через PROPERTY_*, чтобы снизить количество обращений:
$arSelect = [
'ID', 'NAME', 'IBLOCK_ID',
'PROPERTY_COLOR', // одно значение
'PROPERTY_SIZE', // одно значение
'PROPERTY_GALLERY' // множественное (вернутся ID файлов)
];
$arFilter = ['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y'];
$res = CIBlockElement::GetList(['SORT' => 'ASC'], $arFilter, false, ['nTopCount' => 50], $arSelect);
$items = [];
while ($ob = $res->GetNext()) {
// Свойства будут в полях как PROPERTY_COLOR_VALUE и т.п.
$items[] = [
'ID' => $ob['ID'],
'NAME' => $ob['NAME'],
'COLOR' => $ob['PROPERTY_COLOR_VALUE'],
'SIZE' => $ob['PROPERTY_SIZE_VALUE'],
'GALLERY' => (array)$ob['PROPERTY_GALLERY_VALUE'], // массив ID файлов
];
}Плюс: меньше вызовов методов, быстрее на больших выборках. Минус: структура не такая «красивая», как $arResult['PROPERTIES'].
3) ORM D7: Bitrix\Iblock\Elements\ElementXxxTable
Современно и типобезопасно, но требует сгенерированного ORM-класса для ИБ (или использования универсальной ORM).
Пример с сгенерированным классом Elements\ElementCatalogTable (название зависит от кода ИБ):
<?php
use Bitrix\Main\Loader;
use Bitrix\Iblock\Elements\ElementCatalogTable;
Loader::includeModule('iblock');
// SELECT полей и свойств через runtime поля PROPERTY_*
$query = ElementCatalogTable::getList([
'filter' => ['=ACTIVE' => 'Y', '=IBLOCK_ID' => 10],
'select' => [
'ID', 'NAME',
'COLOR' => 'COLOR.VALUE',
'SIZE' => 'SIZE.VALUE',
'GALLERY' => 'GALLERY.VALUE',
],
'limit' => 50,
'order' => ['SORT' => 'ASC']
]);
$rows = $query->fetchAll();
// Свойства сразу доступны как COLOR, SIZE, GALLERYПлюсы:
- Удобно для сложных запросов, joins, строгих выборок.
- Хорошо сочетается с кэшированием D7.
Минусы:
- Нужно подготовить класс, свойства мапятся в runtime поля.
4) Получить только свойства элемента: CIBlockElement::GetProperty
Если поля не нужны, а нужна только конкретная подборка свойств:
$props = [];
$propRes = CIBlockElement::GetProperty($iblockId, $elementId, ['sort' => 'asc'], ['ACTIVE' => 'Y']);
while ($p = $propRes->Fetch()) {
// $p['CODE'], $p['VALUE'], $p['DESCRIPTION'], $p['VALUE_ENUM'], $p['VALUE_XML_ID'] и др.
$code = $p['CODE'] ?: $p['ID']; // у некоторых свойств может не быть кода
if ($p['MULTIPLE'] == 'Y') {
$props[$code]['VALUES'][] = $p;
} else {
$props[$code] = $p;
}
}Плюсы:
- Гибко и быстро, если нужно узкое подмножество.
- Можно фильтровать по коду свойства в 4-м параметре.
5) Кэширование результата (важно для «в любом месте»)
Если этот код будет вызываться на каждом хите (например, в header.php), обязательно добавить кэш:
<?php
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
$cache = Cache::createInstance();
$cacheTtl = 3600;
$cacheId = 'site_settings_'.$iblockId.'_'.$elementId;
$cacheDir = '/my/site_settings';
if ($cache->initCache($cacheTtl, $cacheId, $cacheDir)) {
$data = $cache->getVars();
} elseif ($cache->startDataCache()) {
// получить поля/свойства
$res = CIBlockElement::GetList([], ['IBLOCK_ID'=>$iblockId, 'ID'=>$elementId, 'ACTIVE'=>'Y'], false, ['nTopCount'=>1], ['ID','NAME']);
$data = [];
if ($ob = $res->GetNextElement()) {
$data['FIELDS'] = $ob->GetFields();
$data['PROPERTIES'] = $ob->GetProperties();
}
// Тегированное кэширование — чтобы инвалидация происходила при изменении ИБ
if (defined('BX_COMP_MANAGED_CACHE')) {
global $CACHE_MANAGER;
$CACHE_MANAGER->StartTagCache($cacheDir);
$CACHE_MANAGER->RegisterTag('iblock_id_'.$iblockId);
$CACHE_MANAGER->EndTagCache();
}
$cache->endDataCache($data);
}
// Теперь аналог $arResult['PROPERTIES']:
$props = $data['PROPERTIES'] ?? [];6) Универсальная вспомогательная функция (можно поместить в local/php_interface/init.php или модуль)
Создает привычную структуру с FIELDS и PROPERTIES, похожую на $arResult:
function bxGetIblockElementWithProps(int $iblockId, int $elementId, int $ttl = 3600): array
{
static $prepared = [];
$key = $iblockId.'_'.$elementId.'_'.$ttl;
if (isset($prepared[$key])) {
return $prepared[$key];
}
$data = [];
$cache = Bitrix\Main\Data\Cache::createInstance();
$cacheId = 'bxGetIblockElementWithProps_'.$key;
$cacheDir = '/bx/iblock_element_props';
if ($cache->initCache($ttl, $cacheId, $cacheDir)) {
$data = $cache->getVars();
} elseif ($cache->startDataCache()) {
if (!Bitrix\Main\Loader::includeModule('iblock')) {
$cache->abortDataCache();
return [];
}
$res = CIBlockElement::GetList([], ['IBLOCK_ID'=>$iblockId, 'ID'=>$elementId, 'ACTIVE'=>'Y'], false, ['nTopCount'=>1], ['ID','IBLOCK_ID','NAME','CODE','XML_ID','ACTIVE','SORT','PREVIEW_TEXT','DETAIL_TEXT','PREVIEW_PICTURE','DETAIL_PICTURE']);
if ($ob = $res->GetNextElement()) {
$fields = $ob->GetFields();
$props = $ob->GetProperties();
// Нормализуем множественные свойства: всегда массив
foreach ($props as $code => &$prop) {
if ($prop['MULTIPLE'] === 'Y') {
$prop['VALUE'] = is_array($prop['VALUE']) ? $prop['VALUE'] : (strlen($prop['VALUE']) ? [$prop['VALUE']] : []);
}
}
unset($prop);
$data = [
'FIELDS' => $fields,
'PROPERTIES' => $props,
];
if (defined('BX_COMP_MANAGED_CACHE')) {
global $CACHE_MANAGER;
$CACHE_MANAGER->StartTagCache($cacheDir);
$CACHE_MANAGER->RegisterTag('iblock_id_'.$iblockId);
$CACHE_MANAGER->EndTagCache();
}
$cache->endDataCache($data);
} else {
$cache->abortDataCache();
}
}
return $prepared[$key] = $data;
}Использование в любом месте:
$el = bxGetIblockElementWithProps(10, 123, 1800);
$props = $el['PROPERTIES'];
echo htmlspecialcharsbx($props['MY_PROP']['VALUE']);7) Получить свойства по коду инфоблока и символьному коду элемента
Чтобы не хардкодить ID:
use Bitrix\Iblock\IblockTable;
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
$iblock = IblockTable::getRow(['filter' => ['=CODE' => 'site_settings'], 'select' => ['ID']]);
if ($iblock) {
$iblockId = (int)$iblock['ID'];
$res = CIBlockElement::GetList([], ['IBLOCK_ID' => $iblockId, '=CODE' => 'main'], false, ['nTopCount' => 1], ['ID']);
if ($el = $res->Fetch()) {
$data = bxGetIblockElementWithProps($iblockId, (int)$el['ID']);
$props = $data['PROPERTIES'];
}
}8) Где именно появится $arResult[‘PROPERTIES’] «как в компонентах»
Если нужно именно внутри любого шаблона «как у стандартных компонентов», есть два пути:
- Подключить стандартный компонент с нужными параметрами (например, bitrix:news.detail) и получить
$arResult['PROPERTIES']в его шаблоне. Это нативный способ. - В собственном компоненте в result_modifier.php сформировать
$arResult['PROPERTIES']черезGetProperties(), как показано выше, и использовать вtemplate.php.
Пример в result_modifier.php пользовательского компонента:
if (!empty($arResult['ID']) && Bitrix\Main\Loader::includeModule('iblock')) {
$res = CIBlockElement::GetList([], ['ID' => $arResult['ID']], false, ['nTopCount'=>1], ['ID','IBLOCK_ID']);
if ($ob = $res->GetNextElement()) {
$arResult['FIELDS'] = $ob->GetFields();
$arResult['PROPERTIES'] = $ob->GetProperties();
}
}9) Безопасность и производительность
- Всегда добавляйте кэш для часто читаемых данных (хедер, футер, сайдбары).
- Используйте тегированный кэш с меткой iblock_id_X для автоматической инвалидации при изменениях.
- Ограничивайте выборку через nTopCount и точные фильтры.
- Для файловых свойств используйте
CFile::GetFileArrayодин раз и кладите в кэш. - Экранируйте вывод в шаблонах:
htmlspecialcharsbx, \Bitrix\Main\Text\Converter.
10) Диагностика
- Включайте
Debug/SQLмонитор (performance panel) на деве, чтобы видеть лишние запросы. - Логируйте кэш-промахи и хиты.
- Для ORM — смотрите
$query->getTrackerQuery()(в режиме Debug) для анализа SQL.
Если подскажете, в каком месте и сценарии требуется доступ к свойствам (хедер/футер, конкретный шаблон компонента, кастомная страница, кешируемый блок), будет предложен оптимальный фрагмент с учетом кэша и нагрузки.