Вадим Думбравану руководитель проектов D7. ORM
Object-relational mapping Недостатки текущего похода в API На каждую сущность программируется свой GetList, Update, Add, Delete Различающийся набор параметров Разный синтаксис полей фильтров События могут быть не предусмотрены Разный код под разные БД (Add)
Object-relational mapping Что мы хотим улучшить в ORM Однотипные операции выборки и сохранения в БД для всех сущностей (параметры, фильтры, результаты) Минимальное количество кода для новых сущностей Стандартные события добавления/ изменения/ удаления
Object-relational mapping Реализация сущности (Bitrix\Main\Entity\Base) поля сущностей (Bitrix\Main\Entity\Field и его наследники) датаменеджер (Bitrix\Main\Entity\DataManager) use Bitrix\Main\Entity; class CultureTable extends Entity\DataManager { public static function getTableName() { return 'b_culture'; } public static function getMap() { return array( 'ID' => array( 'data_type' => 'integer', 'primary' => true, 'autocomplete' => true,
Object-relational mapping Описание сущности Название сущности состоит из собственно названия сущности и обязательного суффикса Table. Класс должен быть наследован от Bitrix\Main\Entity\DataManager. Должны быть перекрыты два абстрактных метода getFilePath() и getMap() Метод getTableName() может быть определен и должен вернуть название таблицы. Если метод не определен, то базовая сущность попытается получить имя таблицы автоматически.
Object-relational mapping Поля сущности Поле имеет название (соответствует БД), тип и ряд атрибутов Можно указать первичный ключ Можно указать обязательность и маску Поле может быть вычисляемым Поле может быть ссылкой на другую сущность 'VAT_RATE_PRC' => array( 'data_type' => 'float', 'expression' => array( '100 * %s', 'VAT_RATE' ) ), 'ORDER' => array( 'data_type' => 'Order', 'reference' => array( '=this.ORDER_ID' => 'ref.ID' ) ),
Object-relational mapping Датаменеджер CultureTable::update($ID, $arFields) CultureTable::add($arFields) CultureTable:: delete ($ID) и наш любимый CultureTable::getList($arParams) есть также базовый checkFields(Result $result, array $data, $id = null) Все методы статические. Сущность может переопределить эти базовые методы, если это необходимо.
Object-relational mapping Выборка данных Статический метод getList() с массивом параметров: 'select' – массив выбираемых в SELECT полей; 'filter' – массив условий фильтра для WHERE; 'group' – массив полей для группировки; 'order' – массив сортировки; 'limit' – ограничение количества записей; 'offset' – смещение начала выборки; 'count_total' – нужно ли считать количество записей Метод возвращает объект CDBResult старого ядра. В ближайшем будущем метод будет возвращать объект нового ядра DbResult.
Object-relational mapping Выборка данных $cultureList = CultureTable::getList(array( 'select' =>array('ID', 'NAME'), 'order' => array('NAME' =>'ASC'), 'filter'=>array('CHARSET'=>'Windows-1251'), )); Сортировка может быть по нескольким полям. Фильтр задается в расширенном синтаксисе, который применяется в инфоблоках. Использование параметров, неизвестных методу, приведет к выбросу исключения. Для выборки одной записи по первичному ключу может применяться метод getById()
Object-relational mapping Выборка данных Можно использовать цепочку вызовов методов объекта запроса вместо статического метода. $main_query = new Entity\Query(CultureTable::getEntity()); $main_query->setSelect(array('*')); $main_query->setFilter(array('=ID' => $arParams['ROW_ID'])); $row = $main_query->exec()->Fetch();
Object-relational mapping Модификация данных Статические методы add(), update(), delete() Вызывают соответствующие события. Производят встроенную проверку полей сущностей, вызывая метод checkFields(). Возвращают объекты типов Bitrix\Main\Entity\AddResult, UpdateResult и DeleteResult. Назначение этих объектов – сообщить об успешности операции и дать доступ к ошибкам.
Object-relational mapping Проверка данных Метод checkFields() проверяет поля на обязательные значения (атрибут поля сущности required) и соответствие маске (атрибут format). Для дополнительных проверок класс сущности может переопределить этот метод. В случае ошибки метод должен добавить ошибку в объект результата. Ошибка может быть либо общая для всей сущности, либо относиться к конкретному полю. $result->addError(new Entity\EntityError("Нельзя изменить запись номер 1.")); $result->addError(new Entity\FieldError('NAME', 'Поле «имя» очень странное.'));
Object-relational mapping События Датаменеджер при модификации данных отправляет события. Названия событий строятся автоматически и имеют вид On( Before| | After)( Add| Update| Delete), например CultureOnBeforeDelete. Отменить операцию могут только обработчики событий OnBefore. OnBeforeUpdate(array("id"=>$primary, "fields"=>$data)) checkFields() OnUpdate(array("id"=>$primary, "fields"=>$data)) update OnAfterUpdate(array("id"=>$primary, "fields"=>$data))
Спасибо за внимание! Вопросы?