Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.
Краткие характеристики

Как использовать
Для начала зарегистрируем классы в автолоадере (можно и просто заинклудить):
После чего объявляем свою сущность в соответствии с :
Либо же динамически создаём класс сущности без его явного объявления (как в HL):
Всё! Теперь можно работать с методом MyIblockTable::getList() (или $entityClass::getList()) как с обычной ORM, например:
Как видно, синтаксис запросов всё тот же. Основные моменты:
Главный класс - ElementTable - это наследник от DataManager с getMap() (метод, описывающий поля сущности), который считывает свойства и строит по ним поля-референсы PROPERTY_*. Референсы эти ведут на:
Постраничная навигация
Как выше уже упоминал, постраничка стартует автоматически, если указаны limit и offset в запросе. Поскольку в ORM такое понятие отсутствует, пришлось немного извратиться. Объект \Main\DB\Result (результат работы getList()) дополняется свойством oldCDBResult - старым CDBResult, который содержит стандартную информацию о текущей странице, количестве элементов и т.п, и используется для получения кода постранички. С первого раза, полагаю, понять сложно, поэтому вот пример кодом "было/стало".
Так выглядит классическая постраничка в news.list:
А так выглядит она же, но при выборке через обёртку:
Как видно, поменялось "практически ничего".
Хелпер для получения всех свойств
Чтобы получить свойства элемента, можно в явном виде перечислить их в select. Но если их много или же нужна дополнительная информация о них, можно получить сразу все свойства для всех элементов выборки с помощью вспомогательного метода:
Внутри используется магия \CIBlockElement::GetPropertyValuesArray() - та же, что применяется в catalog.section для существенного сокращения количества запросов к БД по сравнению с _CIBlockElement::GetProperties().
Хелпер для получения Query
Порой при отладке требуется залезть напрямую в объект запроса, но стандартный датаменеджер сразу возвращает объект результата выборки Bitrix\Main\Db\Result. Поэтому был добавлен ещё один метод, являющийся полной копией DataManager::getList(), но возвращающий Bitrix\Main\Entity\Query вместо Result:
Пример компонента
Если вы смогли дочитать до этого места, то наверняка уже заглянули на гитхаб и увидели там . Это простой пример компонента, использующий для вывода списка элементов orm-обёртку. Изначально это был компонент в рабочем проекте, из которого я выпилил всю лишнюю логику, но не стал менять общей структуры, поэтому он может выглядеть монструозно. Основная логика находится в методах getItems() и formatResult(). А ещё в качестве бонуса там остался закомментированный код для реализации постранички со своей переменной/чпу.
Вместо тысячи слов
Просто для демонстрации - пример скомпанованного запроса с фильтром по свойствам инфоблока и сторонней таблице и сортировкой по агрегированному полю сторонней таблицы. Быстро, просто и безболезненно.
Назад в раздел
Наверх
то ждем ваше обращение в нашей службе тех поддержки.
ORM-обёртка для инфоблоков
Потребовалось для одного проекта скрестить инфоблоки с собственными таблицами, всяческими сквозными фильтрами и сортировками. Да и ещё и работало чтоб быстро. Первое, что приходит на ум - ORM. Но она в инфоблоках пока отсутствует (точнее, отсутствует самая нужная её часть - работа с элементами), поэтому пришлось реализовывать свою прослойку, которой и хочу поделиться -Краткие характеристики
- Доступна вся мощь getlist'а orm и sql-билдера - связывание и подтягивание данных откуда угодно и как угодно (, ).
- Возможна работа как с заранее описанными сущностями (наследниками обёртки), так и с динамически создаваемыми (аналогично hlblock'ам).
- Поддержка стандартной постраничной навигации. Пока в ORM её нет, поэтому пришлось немного костыльнуть, зато поддерживается стандартный system.pagenavigation.
- Хелпер для получения всех свойств элементов в выборке (описано ниже).
- Только для ИБ 2.0. При особом желании можно и под первые адаптировать, но не было необходимости.
- Read only. Создания и модификация элементов через эту обёртку невозможны, для этого есть замечательное классическое апи.
- Доступ к элементам по правам - на совести конечного разработчика, обёртка не предлагает никакого функционала, но предоставляет все возможности для его реализации.
- ElementTable - главный класс, наследуется от orm'ного DataManager. Через него происходит вся работа.
- MultiplePropertyElementTable - служебная сущность, описывающая множественные свойства инфоблока.
- SinglePropertyElementTable - аналогично предыдущему, только для единичных.

Как использовать
Для начала зарегистрируем классы в автолоадере (можно и просто заинклудить):
\CModule::AddAutoloadClasses('', array(
'nav\\IblockOrm\\MultiplePropertyElementTable' => '/local/lib/nav/IblockOrm/MultiplePropertyElementTable.php',
'nav\\IblockOrm\\SinglePropertyElementTable' => '/local/lib/nav/IblockOrm/SinglePropertyElementTable.php',
'nav\\IblockOrm\\ElementTable' => '/local/lib/nav/IblockOrm/ElementTable.php',
)); |
После чего объявляем свою сущность в соответствии с :
class MyIblockTable extends \nav\IblockOrm\ElementTable
{
static protected $_iblockId = 1;
} |
Либо же динамически создаём класс сущности без его явного объявления (как в HL):
$entity = \nav\IblockOrm\ElementTable::createEntity($iblockId); $entityClass = $entity->getDataClass(); |
Всё! Теперь можно работать с методом MyIblockTable::getList() (или $entityClass::getList()) как с обычной ORM, например:
MyIblockTable::getList(array(
'order' => array('PROPERTY_POPULAR' => 'ASC'),
'filter' => array(
'=ACTIVE' => 'Y',
'!PROPERTY_NEW' => false,
),
)); |
Как видно, синтаксис запросов всё тот же. Основные моменты:
- Свойства доступны по коду PROPERTY_CODE, где CODE - символьный код свойства (как в обычном гетлисте).
- Если свойства есть в select, то их значения в результате будут находиться в тех же ключах, если не было задано алиасов (в апи инфоблоков, как помните, они находятся в PROPERTY_CODE_VALUE).
- Поля при получении экранируются htmlspecialcharsbx(), оригинальные значения лежат в ключах с префиксом ~ (аналогично обычному гетлисту).
- По умолчанию ORM выбирает только скалярные поля, поэтому для получения желаемых свойств их надо явно указывать в select. Либо использовать хелпер для получения всех свойств.
- Для получения ссылки на элемент надо в select указать DETAIL_PAGE_URL. Это динамически вычисляемое поле, поэтому по умолчанию оно не заполняется.
- Постраничная навигация стартует автоматически, если в выборке были указаны и limit, и offset.
- При фильтре по множественному свойству элементы могут дублироваться. Чтобы этого избежать, надо добавить в select поле DISTINCT (см. комментарии к посту).
Главный класс - ElementTable - это наследник от DataManager с getMap() (метод, описывающий поля сущности), который считывает свойства и строит по ним поля-референсы PROPERTY_*. Референсы эти ведут на:
- SinglePropertyElementTable для единичных свойств. На каждый инфоблок (читай класс) присутствует только один референс на SinglePropertyElementTable и он доступен по ключу PROPERTY. Поля референса - это символьные коды свойств. Таким образом, в гетлисте мы можем обращаться к свойствам по ключу PROPERTY.CODE. Предлагаемые же PROPERTY_CODE сделаны просто для удобства и совместимости с обычным апи инфоблоков и являются референсами на поля сущности SingleProperty.
- MultiplePropertyElementTable. Поскольку у каждого множественного свойства своя таблица в БД, то и сущностей MultipleProperty создаётся на каждое свойство по одной. Сущности доступны по ключу PROPERTY_CODE_ENTITY. Так как таблицы множественных свойств имеют разные колонки в зависимости от типа свойства (VALUE, VALUE_ENUM, VALUE_NUM), не пренебрегайте фильтр через эту сущность для достижения наилучшей производительности (вообще при работе с любой orm-сущностью советую всегда мониторить генерируемый sql, встречаются подвохи). Для сущности элемента инфоблока PROPERTY_CODE является референсом PROPERTY_CODE_ENTITY.VALUE.
Постраничная навигация
Как выше уже упоминал, постраничка стартует автоматически, если указаны limit и offset в запросе. Поскольку в ORM такое понятие отсутствует, пришлось немного извратиться. Объект \Main\DB\Result (результат работы getList()) дополняется свойством oldCDBResult - старым CDBResult, который содержит стандартную информацию о текущей странице, количестве элементов и т.п, и используется для получения кода постранички. С первого раза, полагаю, понять сложно, поэтому вот пример кодом "было/стало".
Так выглядит классическая постраничка в news.list:
$rsElement = CIBlockElement::GetList(...); ... $arResult["NAV_STRING"] = $rsElement->GetPageNavStringEx($navComponentObject, $arParams["PAGER_TITLE"], $arParams["PAGER_TEMPLATE"], $arParams["PAGER_SHOW_ALWAYS"]); $arResult["NAV_CACHED_DATA"] = $navComponentObject->GetTemplateCachedData(); $arResult["NAV_RESULT"] = $rsElement; |
А так выглядит она же, но при выборке через обёртку:
$rsElement = MyIblockTable::getList(...); ... $arResult['NAV_STRING'] = $rsElement->oldCDBResult->GetPageNavStringEx($navComponentObject, $arParams["PAGER_TITLE"], $arParams["PAGER_TEMPLATE"], $arParams["PAGER_SHOW_ALWAYS"]); $arResult['NAV_CACHED_DATA'] = $navComponentObject->GetTemplateCachedData(); $arResult['NAV_RESULT'] = $rsElement->oldCDBResult; |
Как видно, поменялось "практически ничего".
Хелпер для получения всех свойств
Чтобы получить свойства элемента, можно в явном виде перечислить их в select. Но если их много или же нужна дополнительная информация о них, можно получить сразу все свойства для всех элементов выборки с помощью вспомогательного метода:
$rs = MyIblockTable::getList(...); $arItems = MyIblockTable::fetchAllWithProperties($rs); |
Внутри используется магия \CIBlockElement::GetPropertyValuesArray() - та же, что применяется в catalog.section для существенного сокращения количества запросов к БД по сравнению с _CIBlockElement::GetProperties().
Хелпер для получения Query
Порой при отладке требуется залезть напрямую в объект запроса, но стандартный датаменеджер сразу возвращает объект результата выборки Bitrix\Main\Db\Result. Поэтому был добавлен ещё один метод, являющийся полной копией DataManager::getList(), но возвращающий Bitrix\Main\Entity\Query вместо Result:
$query = MyIblockTable::getQuery(...) |
Пример компонента
Если вы смогли дочитать до этого места, то наверняка уже заглянули на гитхаб и увидели там . Это простой пример компонента, использующий для вывода списка элементов orm-обёртку. Изначально это был компонент в рабочем проекте, из которого я выпилил всю лишнюю логику, но не стал менять общей структуры, поэтому он может выглядеть монструозно. Основная логика находится в методах getItems() и formatResult(). А ещё в качестве бонуса там остался закомментированный код для реализации постранички со своей переменной/чпу.
Вместо тысячи слов
Просто для демонстрации - пример скомпанованного запроса с фильтром по свойствам инфоблока и сторонней таблице и сортировкой по агрегированному полю сторонней таблицы. Быстро, просто и безболезненно.
$this->rs = \nav\PlaceTable::getList(array(
'select' => array('ID', 'NAME', 'DETAIL_PICTURE', 'PREVIEW_TEXT', 'DETAIL_TEXT', 'DETAIL_PAGE_URL', 'PRICE_SORT'),
'order' => array('PRICE_SORT' => 'DESC'),
'filter' => array(
'=ACTIVE' => 'Y',
'=WF_STATUS_ID' => 1,
'WF_PARENT_ELEMENT_ID' => false,
'><\\nav\\PriceDayTable:PLACE.PRICE' => array(12000, 32100),
'\\nav\\PriceDayTable:PLACE.DATE' => new \Bitrix\Main\Type\Date('01/06/15', 'd/m/y'),
'=PROPERTY_TYPE' => array(208, 209, 5302),
),
'group' => array('ID'),
'limit' => $arNavigation['SIZEN'],
'offset' => $arNavigation['SIZEN'] * ($arNavigation['PAGEN'] - 1),
'runtime' => array(
'PRICE_SORT' => array(
'expression' => array('MIN(%s)', '\nav\PriceDayTable:PLACE.PRICE')
),
),
));
$this->items = \nav\PlaceTable::fetchAllWithProperties($this->rs);
|
Назад в раздел
Подписаться на новые материалы раздела:
Загрузка...
Наверх