Appearance
Orm
Orm - Object-relational mapping - Объектно-реляционное отображение - технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования. Другими словами Orm позволяет работать не с массивами данных (строками таблицы в БД), а с объектами. Подробнее про приемущества работы с объектами
База данных
С точки зрения realweb.api и bitrix каждый отдельный инфоблок представляет собой отдельную таблицу
Класс базы данных содержит основной запрос к БД. Класс должен реализовывать следующие методы:
public static function getQuery(?\Realweb\Api\Model\Main\Pagination $obNav = null)- основной запрос для получения записейpublic static function getOrmEntity(): \Bitrix\Main\ORM\Entity- Получение Orm сущности битриксаpublic static function getEntity(): string- получение класса записи в БД (\Realweb\Api\Model\Data\Entity)public static function getCollection(): string- получение класса коллекции записей в БД (\Realweb\Api\Model\Data\Collection)
Имеет ряд часто используемых методов:
public static function getObjectCollection(?Pagination $obNav = null): Collection- получение коллекции сущностей, параметры запроса передаются в объекте пагинацииpublic static function getObject(?Pagination $obNav = null): Entity- получение сущности, параметры запроса передаются в объекте пагинацииpublic static function getByPrimary($mPrimary): Entity- получение сущности по первичному ключу, если сущность не найдена возвратит новую сущность.public static function getAll(?Pagination $obNav = null): array- получение массива данных из БД, параметры запроса передаются в объекте пагинацииpublic static function getRow(?Pagination $obNav = null): ?array- получение строки данных из БД в виде массива (или null), параметры запроса передаются в объекте пагинации
Запрос в БД
Метод получения запроса getQuery должен возвращать объект класса \Realweb\Api\Model\Orm\Query. Данный класс расширяет стандартный \Bitrix\Main\ORM\Query\Query и обладает дополнительными методами (для удобства составления запросов)
public function registerFileField(string $field, bool $withSize = false): self- Добавление в запрос пути к файлуpublic function registerFileSizeField(string $strFieldName): self- Добавление в запрос пути к файлу с параметрами высоты и шириныpublic function whereCustom(string $field, $value, string $condition = '='): self- Добавление условия равенства, в зависимости от входящих данных
Коллекция
Коллекция представляет собой экземпляр класса \Realweb\Api\Model\Data\Collection и необходим для хранения списка сущностей. Коллекция - контейнер для хранения массива объектов сущностей. Позволяет искать сущности по первичному (и не только) ключу. Каждая сущность должна обладать таким уникальным ключом (В общем случае ID)
В отличие от массива сущностей обладает рядом преимуществ: поиск по уникальному "ключу" (В большинстве случаев это ID), манипуляции со списком сущностей, также, как и массив итерабельна
Должна реализовывать метод public function addItem($obItem): self - добавление сущности в контейнер.
Имеет встроенные методы:
public function getByKey($strKey)- Поиск сущности по первичному ключуpublic function deleteByKey($strKey): self- Удаление сущности по первичному ключуpublic function count(): int- количество сущностей в контейнереpublic function getCollection(): array- получение массива сущностей в коллекцииpublic function getKeys(): array- получение уникальных ключей сущностейpublic function current()- текущий элемент коллекцииpublic function toJson(): array- последовательно вызывает метод toJson, складывает результат в массив и возвращает его
Также, может иметь магические методы toJson*. В таком случае, класс сущности в коллекции также должен реализовывать этот метод.
Для операции с сущностями внутри коллекции (например, получение каких либо связанных с каждой сущностью данных) стоит использовать методы process*
Пример
php
use Realweb\Api\Module\Catalog;
$obCollection = Catalog\Model\Section\Database::getObjectCollection($obNav);
$obCollection->processPoints();
class Collection extends \Realweb\Api\Model\Iblock\Section\Collection
{
/**
* @return Entity[]
*/
public function getCollection(): array
{
return parent::getCollection();
}
public function getByKey($strKey): ?Entity
{
return parent::getByKey($strKey);
}
public function processPoints(): void
{
if ($this->count() > 0) {
$obPoints = (new \Realweb\Api\Module\Points\Controller\ElementController())
->setParam('iblock_section_ids', $this->getKeys())
->getCollection()
;
foreach ($obPoints->getCollection() as $obPoint) {
if ($obSection = $this->getByKey($obPoint->getIblockSectionId())) {
$obSection->getElements()->addItem($obPoint);
}
}
}
}
}Внимание!
Не стоит использовать контейнер и хранить в кеше коллекции с большим количество сущностей (~1000 и более)
Таблицы
Для работы со своими таблицами (Или с таблицами битрикс, для которых еще нет orm представления в ядре битрикса) следует использовать класс \Realweb\Api\Model\Orm\DataManager.
Он наследуется от стандартного \Bitrix\Main\ORM\Data\DataManager, но обладает преимуществом простого и понятного сохранения структуры таблицы.
Таблица в БД синхронизируется с описанной в классе таблицы схемой. Новые поля появятся, удаленные исчезнут (вместе с созданными внешними ключами, если таковые были)
Для всех полей учитываются следующие методы:
configureSize- размер поляconfigureNullable- возможность храненияnullзначенияconfigureDefaultValue- значение по умолчаниюconfigureAutocomplete- автокомплит поля (ID)configurePrimary- первичный ключ
Для полей, у которых отсутствует метод configureSize можно указать новый параметр size
Пример
php
namespace Realweb\Api\Module\User\Model\Transaction;
use Realweb\Api\Model\Orm\DataManager;
/**
* Class \Realweb\Api\Module\User\Model\Transaction\Table
*/
class Table extends DataManager
{
public static function getTableName(): string
{
return 'realweb_user_transaction';
}
public static function getMap(): array
{
return array(
(new \Bitrix\Main\Entity\IntegerField('ID'))
->configurePrimary()->configureAutocomplete(),
(new \Bitrix\Main\Entity\IntegerField('USER_ID_FROM')),
(new \Bitrix\Main\Entity\IntegerField('USER_ID_TO')),
(new \Bitrix\Main\Entity\DatetimeField('DATE_TIME')),
(new \Bitrix\Main\Entity\IntegerField('AMOUNT')),
(new \Bitrix\Main\Entity\TextField('MESSAGE')),
(new \Bitrix\Main\Entity\StringField('CODE')),
(new \Bitrix\Main\Entity\StringField('PHONE')),
(new \Bitrix\Main\Entity\IntegerField('SUCCESS')),
((new \Bitrix\Main\ORM\Fields\Relations\Reference(
'USER_FROM',
\Realweb\Api\Model\User\Table\UserTable::class,
\Bitrix\Main\ORM\Query\Join::on('this.USER_ID_FROM', 'ref.ID')
))->configureJoinType(\Bitrix\Main\ORM\Query\Join::TYPE_LEFT)),
((new \Bitrix\Main\ORM\Fields\Relations\Reference(
'USER_TO',
\Realweb\Api\Model\User\Table\UserTable::class,
\Bitrix\Main\ORM\Query\Join::on('this.USER_ID_TO', 'ref.ID')
))->configureJoinType(\Bitrix\Main\ORM\Query\Join::TYPE_LEFT)),
);
}
public static function query(): \Realweb\Api\Model\Orm\Query
{
return new \Realweb\Api\Model\Orm\Query(static::getEntity());
}
}Сохранение(обновление) таблицы
php
\Realweb\Api\Module\User\Model\Transaction\Table::saveTable();Индексы
Для того чтобы добавить индекс, необходимо зарегистрировать в таблице поле с классом \Realweb\Api\Model\Orm\Field\Index. Индексы могут быть по одному или по нескольким полям
Пример
php
public static function getMap(): array
{
return array(
(new \Bitrix\Main\ORM\Fields\IntegerField('ID'))
->configurePrimary()
->setParameter(self::PARAM_SIZE, 11)
->configureAutocomplete(),
(new \Bitrix\Main\ORM\Fields\DatetimeField('DATE_CREATE')),
(new \Bitrix\Main\ORM\Fields\DatetimeField('DATE_EXEC')),
(new \Bitrix\Main\ORM\Fields\StringField('NAME'))->configureSize(255),
(new \Bitrix\Main\ORM\Fields\IntegerField('STATUS'))
->setParameter(self::PARAM_SIZE, 1),
(new \Bitrix\Main\ORM\Fields\IntegerField('ELEMENT_ID')),
(new \Realweb\Api\Model\Orm\Field\Index('STATUS_ELEMENT_ID'))
->addField("STATUS")
->addField("ELEMENT_ID"),
);
}Внешние ключи
Для того чтобы указать внешний ключ для поля, необходимо зарегистрировать в таблице поле с классом \Realweb\Api\Model\Orm\Field\ForeignKey и указать необходимые параметры.
setTableName- название таблицы для связиsetField- название поля текущей таблицыsetTableField- название поля в связываемой таблицеsetOnDelete- поведение при удалении
Пример
php
public static function getMap(): array
{
return array(
(new \Bitrix\Main\ORM\Fields\IntegerField('ID'))
->configurePrimary()
->setParameter(self::PARAM_SIZE, 11)
->configureAutocomplete(),
(new \Bitrix\Main\ORM\Fields\DatetimeField('DATE_CREATE')),
(new \Bitrix\Main\ORM\Fields\DatetimeField('DATE_EXEC')),
(new \Bitrix\Main\ORM\Fields\StringField('NAME'))->configureSize(255),
(new \Bitrix\Main\ORM\Fields\IntegerField('STATUS'))
->setParameter(self::PARAM_SIZE, 1),
(new \Bitrix\Main\ORM\Fields\IntegerField('ELEMENT_ID')),
(new \Realweb\Api\Model\Orm\Field\ForeignKey('ELEMENT_ID_BITRIX'))
->setTableName(\Bitrix\Iblock\ElementTable::getTableName())
->setField("ELEMENT_ID")
->setTableField("ID")
->setOnDelete(\Realweb\Api\Model\Orm\Field\ForeignKey::ON_DELETE_CASCADE),
);
}