Содержание
Сниппеты getMap()
getMap
используется для описания схемы БД в ORM. Сниппеты ниже следует использовать в return […]
Entity\DataManager::getMap()
Сериализация при сохранении и десериализация при выборке
new Entity\TextField('DEBT_DATA_RAW', [ 'save_data_modification' => function () { return [ function ($value) { return serialize($value); } ]; }, 'fetch_data_modification' => function () { return [ function ($value) { return unserialize($value); } ]; } ]),
ID
new Entity\IntegerField('ID', [ 'primary' => true, 'autocomplete' => true ]),
GUID
new Entity\StringField('PARTNER_GUID', [ 'primary' => true, 'size' => 36 ]),
Datetime
new Entity\DatetimeField('DATE_CREATED', []), new Entity\DatetimeField('DATE_UPDATED', [ 'default_value' => new \Bitrix\Main\Type\Datetime ]),
Булево значение да/нет
new Entity\BooleanField('ACTIVE', [ 'values' => ['Y', 'N'], 'default_value' => 'Y' ]),
ReferenceField
Привязка одного элемента к другому, или внешний ключ на другую сущность.
Привязка к инфоблоку ElementTable по ID, XML_ID, NAME
Так выглядит привязка к элементу инфоблока с номером 51, по XML_ID
:
new Entity\ReferenceField( 'PARTNER', 'Bitrix\Iblock\ElementTable', [ '=this.PARTNER_GUID' => 'ref.XML_ID', '=ref.IBLOCK_ID' => new \Bitrix\Main\DB\SqlExpression('?i', 51) ] ),
Вообще, возможно привязываться таким способом к ID
, XML_ID
, NAME
и другим полям, описанным в ElementTable
. Однако если для привязки в «привязываемом элементе» используется свойство, это будет сделать проблематично (см ниже).
Привязка к инфоблоку ElementTable по свойству
Допустим, есть элемент инфоблока с номером ID
, и мы создаем схему этой сущности. В другом инфоблоке есть элемент, у которого заведено свойство TENDER_ID
, который ссылается на описываемую сущность:
- tenderrequest.php
new Entity\ReferenceField( '1C', 'Vendor\Logistic\Orm\Arrival\OneSPropsTable', [ '=this.ID' => 'ref.TENDER_ID', ] ),
Как сделать привязку через getMap()
? Дело осложняется тем, что свойства представляют собой отдельные записи в таблице b_iblock_element_property
, поэтому еще необходимо самообъединение таблиц. Все эти свойства можно получить через запрос:
SELECT * FROM b_iblock_element_property WHERE IBLOCK_ELEMENT_ID = 4994277;
Эту проблему я решил через SQL представление:
DROP VIEW IF EXISTS `vendor_logistic_1c_info`; CREATE VIEW `vendor_logistic_1c_info` AS SELECT prim.VALUE_NUM AS `TENDER_ID`, prop_1.VALUE AS `KOD_RS`, prop_2.VALUE AS `NAME_RS`, prop_3.VALUE AS `ZAKAZ`, prop_4.VALUE AS `ITEM_NUM` FROM `b_iblock_element_property` AS `prim` JOIN `b_iblock_element_property` AS `prop_1` ON (prim.IBLOCK_ELEMENT_ID = prop_1.IBLOCK_ELEMENT_ID AND prop_1.IBLOCK_PROPERTY_ID = 279) JOIN `b_iblock_element_property` AS `prop_2` ON (prim.IBLOCK_ELEMENT_ID = prop_2.IBLOCK_ELEMENT_ID AND prop_2.IBLOCK_PROPERTY_ID = 280) JOIN `b_iblock_element_property` AS `prop_3` ON (prim.IBLOCK_ELEMENT_ID = prop_3.IBLOCK_ELEMENT_ID AND prop_3.IBLOCK_PROPERTY_ID = 281) JOIN `b_iblock_element_property` AS `prop_4` ON (prim.IBLOCK_ELEMENT_ID = prop_4.IBLOCK_ELEMENT_ID AND prop_4.IBLOCK_PROPERTY_ID = 282) WHERE prim.IBLOCK_PROPERTY_ID = 278; -- демонстрация работы SELECT sql_no_cache * FROM vendor_logistic_1c_info WHERE TENDER_ID = 4979188;
Для быстрой работы запроса используется prim.VALUE_NUM AS `TENDER_ID`
(хранит тип DECIMAL), а не prim.VALUE
(тип VARCHAR).
- onesprops.php
namespace Vendor\Logistic\Orm\Arrival; use \Bitrix\Main\Entity; class OneSPropsTable extends Entity\DataManager { public static function getTableName() { return 'vendor_logistic_1c_info'; } public static function getMap() { return [ new Entity\StringField('ITEM_NUM', ['primary' => true]), new Entity\IntegerField('TENDER_ID'), new Entity\StringField('KOD_RS'), new Entity\StringField('NAME_RS'), new Entity\StringField('ZAKAZ'), ]; } }
Привязка к пользователю UserTable
new Entity\ReferenceField( 'USER', 'Bitrix\Main\UserTable', ['=this.USER_ID' => 'ref.ID'] ),
ExpressionField
Удобно задавать алиасы, чтобы названия столбцов были читаемые. %s
рекоментуется использовать везде, чтобы работала фильтрация, заданная перечислением «=PARTNER_NAME» ⇒ […]
new Entity\ExpressionField('PARTNER_NAME', '%s', 'PARTNER.DETAIL_TEXT'),
Более продвинутый вариант, когда данные нужно дополнительно обрабатывать:
new Entity\ExpressionField('UNLOADING_DATE', '%s', 'PROPS.PROPERTY_241', // Дата разгрузки [ 'save_data_modification' => function () { return [ function ($value) { return serialize($value); } ]; }, 'fetch_data_modification' => function () { return [ function ($value) { return unserialize($value); } ]; } ] ),
Форматирование даты:
new Entity\ExpressionField('ACTIVE_FROM', "DATE_FORMAT(ACTIVE_FROM, '%%d.%%m.%%Y %%H:%%m:%%S')"),
new Entity\ExpressionField(«LOADING_DATE», «%s», «PROPS.PROPERTY_238»)
работать не будет, связано с форматированием даты в другом формате. Следует использовать так: «=PROPS.PROPERTY_238»