Ядро
D7 ORM, Query и Join
Рабочая справка по D7 ORM в Bitrix Framework: Table-классы, getList, Query, runtime-поля, ReferenceField и Join.
D7 ORM удобен, когда нужно читать и изменять данные через Table-классы. Для простых выборок
часто хватает getList(), для сложных связей удобнее использовать
Query и runtime-поля.
D7 ORM
ORM в D7 строится вокруг Table-классов, которые описывают таблицу и её поля.
Что такое Table-класс
Table-класс обычно наследуется от DataManager и описывает имя таблицы и
карту полей.
<?php
namespace test\Example\Model;
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Fields;
class ExampleTable extends DataManager
{
/**
* Возвращает имя таблицы.
*/
public static function getTableName(): string
{
return 'b_test_example_item';
}
/**
* Возвращает карту полей.
*/
public static function getMap(): array
{
return [
new Fields\IntegerField('ID', [
'primary' => true,
'autocomplete' => true,
]),
new Fields\StringField('TITLE', [
'required' => true,
]),
new Fields\IntegerField('CRM_ENTITY_ID'),
];
}
} getList
getList() — основной способ получить список записей из ORM-таблицы.
<?php
use test\Example\Model\ExampleTable;
/**
* Получает элементы по ID CRM-сущности.
*/
function fetchItemsByCrmEntityId(int $crm_entity_id): array
{
$items = [];
$item_result = ExampleTable::getList([
'select' => [
'ID',
'TITLE',
'CRM_ENTITY_ID',
],
'filter' => [
'=CRM_ENTITY_ID' => $crm_entity_id,
],
'order' => [
'ID' => 'ASC',
],
'limit' => 100,
]);
while ($item = $item_result->fetch()) {
$items[] = $item;
}
return $items;
}
$items = fetchItemsByCrmEntityId($crm_entity_id);
print_r($items); add, update, delete
<?php
use test\Example\Model\ExampleTable;
/**
* Добавляет элемент.
*/
function addExampleItem(string $title, int $crm_entity_id): array
{
$result = ExampleTable::add([
'TITLE' => $title,
'CRM_ENTITY_ID' => $crm_entity_id,
]);
return [
'is_success' => $result->isSuccess(),
'item_id' => (int) $result->getId(),
'error_messages' => $result->getErrorMessages(),
];
}
/**
* Изменяет название элемента.
*/
function updateExampleItemTitle(int $item_id, string $title): array
{
$result = ExampleTable::update($item_id, [
'TITLE' => $title,
]);
return [
'is_success' => $result->isSuccess(),
'error_messages' => $result->getErrorMessages(),
];
}
/**
* Удаляет элемент.
*/
function deleteExampleItem(int $item_id): array
{
$result = ExampleTable::delete($item_id);
return [
'is_success' => $result->isSuccess(),
'error_messages' => $result->getErrorMessages(),
];
} Query
Query удобен, когда нужно собрать выборку пошагово.
Когда нужен Query
- нужно собрать сложную выборку постепенно;
- нужно добавить runtime-поля;
- нужно посмотреть итоговый SQL;
- нужно настроить join или выражение.
setSelect, setFilter, setOrder
<?php
use Bitrix\Main\ORM\Query\Query;
use test\Example\Model\ExampleTable;
/**
* Получает элементы через объект Query.
*/
function fetchItemsWithQuery(int $crm_entity_id): array
{
$query = new Query(ExampleTable::getEntity());
$query->setSelect([
'ID',
'TITLE',
'CRM_ENTITY_ID',
]);
$query->setFilter([
'=CRM_ENTITY_ID' => $crm_entity_id,
]);
$query->setOrder([
'ID' => 'ASC',
]);
$query->setLimit(100);
return $query->exec()->fetchAll();
}
$items = fetchItemsWithQuery($crm_entity_id);
print_r($items); Посмотреть SQL
При отладке сложных ORM-запросов удобно вывести итоговый SQL.
<?php
use Bitrix\Main\ORM\Query\Query;
use test\Example\Model\ExampleTable;
/**
* Возвращает SQL ORM-запроса.
*/
function fetchItemsQuerySql(int $crm_entity_id): string
{
$query = new Query(ExampleTable::getEntity());
$query
->setSelect([
'ID',
'TITLE',
])
->setFilter([
'=CRM_ENTITY_ID' => $crm_entity_id,
]);
return $query->getQuery();
}
$sql = fetchItemsQuerySql($crm_entity_id);
echo $sql; Join
Связи в ORM можно описывать через runtime-поля и ReferenceField.
ReferenceField
Пример: у своей таблицы есть CRM_ENTITY_ID, а нужно подтянуть данные
пользователя из UserTable.
<?php
use Bitrix\Main\UserTable;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Query\Join;
use test\Example\Model\ExampleTable;
/**
* Получает элементы с ответственным пользователем.
*/
function fetchItemsWithUser(): array
{
return ExampleTable::getList([
'select' => [
'ID',
'TITLE',
'USER_ID',
'USER_NAME' => 'USER.NAME',
'USER_LAST_NAME' => 'USER.LAST_NAME',
],
'runtime' => [
new Reference(
'USER',
UserTable::class,
Join::on('this.USER_ID', 'ref.ID')
),
],
'order' => [
'ID' => 'ASC',
],
'limit' => 100,
])->fetchAll();
}
$items = fetchItemsWithUser();
print_r($items); Join::on
Join::on() делает условие связи читаемее: слева поле текущей таблицы,
справа поле связанной таблицы.
new Reference(
'USER',
UserTable::class,
Join::on('this.USER_ID', 'ref.ID')
); join_type
Если нужен не левый join, можно указать тип соединения.
new Reference(
'USER',
UserTable::class,
Join::on('this.USER_ID', 'ref.ID'),
[
'join_type' => 'inner',
]
);