ORM в D7 1c-bitrix. Первый подход к снаряду
Реализация ORM в ядре D7 — очередная интересная, перспективная, но как обычно плохо документированная разработка от 1с-Битрикс :) Призвана она абстрагировать разработчика от механики работы с таблицами на уровне запросов к БД, введя понятие сущности и поля сущности. На зимней партнерской конференции Алексей Кирсанов провел мастер-класс по созданию модуля с применением ORM для выборки данных из своей таблицы. После чего я решил провести небольшое исследование на предмет возможности построения более сложных, чем в примере, запросов.
Интересовало меня как общее устройство системы и принцип постороения кода, так и частные случаи запросов. Например, можно ли с помощью ORM использовать HAVING, DISTINCT и разные типы JOIN’ов. Забегая вперед, получилось далеко не все, но в общем конструктор эффективен и относительно прост.
Для начала изучаем понятия сущности, поля сущности и датаменеджера в документации. По-простому, сущность в терминах битрикса — это таблица, поля сущности — столбцы или «ссылки» на другие сущности, а датаменеджер — система управления данными. Для каждой сущности нужно создать описание, например
class ElementTable extends Entity\DataManager { public static function getFilePath() { return __FILE__; } public static function getTableName() { return 'b_iblock_element'; } public static function getMap() { return array( 'ID' => array( 'data_type' => 'integer', 'primary' => true, 'autocomplete' => true, 'title' => Loc::getMessage('IBLOCK_ELEMENT_ENTITY_ID_FIELD'), ), 'IBLOCK_ID' => array( 'data_type' => 'integer', ), 'IBLOCK' => array( 'data_type' => 'Iblock', 'reference' => array('=this.IBLOCK_ID' => 'ref.ID'), ), ...
В getMap перечислены все поля таблицы, включая описание связей с другими сущностями. В примере таким образом указано отношение столбца IBLOCK_ID текущей таблицы и столбца ID сущности Iblock. В дальнейшем по reference-полям возможно выбирать поля связанных сущностей и использовать их в фильтрах.
Лайвхак: автоматически сгенерировать класс с описанием любой таблицы можно на странице Производительность-Таблицы, добавив параметр &orm=y в адрес.
Тренироваться будем на таблицах типов инфоблока, самих инфоблоков и элементов. Для них описаны сущности TypeTable, IblockTable и ElementTable, их можно посмотреть в исходниках модуля iblock. Операции добавления, удаления и выборки данных по первичному ключу (getById) нас не интересуют, будем строить обычные getList-запросы произвольного вида через цепочку вызовов методов класса Query.
Пример #1
Выберем 10 первых элементов из инфоблока ID=1.
\Bitrix\Main\Loader::IncludeModule("iblock"); // создаем объект Query. В качестве параметра он принимает объект сущности, относительно которой мы строим запрос $query = new \Bitrix\Main\Entity\Query(Bitrix\Iblock\ElementTable::getEntity()); // можно еще так: :) // $query = new \Bitrix\Main\Entity\Query(Bitrix\Main\Entity\Base::getInstance("Bitrix\Iblock\ElementTable")); $query ->setSelect(array("ID", "NAME")) ->setFilter(array("IBLOCK_ID" => 1)) ->setOrder(array("ID" => "ASC")) ->setLimit(10); $query->exec(); $query->dump();
Пример #2
Выберем элементы инфоблока с группировкой по названию. Стоит отметить, что битрикс автоматически добавляет в число полей для группировки все, что указано в setSelect.
$query ->setSelect(array("NAME")) ->setFilter(array("IBLOCK_ID" => 1)) ->setGroup(array("NAME"))
Пример #3
В запросах можно использовать агрегатные функции mysql. Для это служит метод registerRuntimeField, регистрирующий новое поле на время выполнения запроса.
Подсчитаем количество элеметов с группировкой по имени.
$query // cnt - название поля ->registerRuntimeField("cnt", array( // тип вычисляемого поля "data_type" => "integer", // агрегатная функция (count, max, sum, avg...) и поле для подстановки "expression" => array("count(%s)", "NAME") ) ) ->setSelect(array("NAME", "cnt")) ->setFilter(array("IBLOCK_ID" => 1)) ->setGroup(array("NAME"));
Пример #4
Допустим, нам нужно в предыдущем примере ограничить выборку только теми названиями, которые встречаются более 5 раз. Написав фильтр по агрегатному runtime-полю, битрикс автоматически переносит его в условие having! Причем в параметрах группировки не обязательно указывать поле, к которому применяется агрегатная функция.
$query ->registerRuntimeField("cnt", array( "data_type" => "integer", "expression" => array("count(%s)", "NAME") ) ) ->setSelect(array("NAME", "cnt")) ->setFilter(array("IBLOCK_ID" => 1, ">cnt" => 5));
Будет сгенерирован запрос вида:
select NAME, count(NAME) as cnt from table where IBLOCK_ID=1 group by NAME having cnt>5
Пример #5
Через сущность «элемент» можно выбирать или ставить условия на поля связанной сущности «инфоблок». Связанная таблица по умолчанию присоединяется с помощью left join. Вспомним reference-поле IBLOCK в описании ElementTable и выберем название инфоблока с ID=1 через таблицу с элементами:
$query ->setSelect(array("IBLOCK.NAME")) ->setFilter(array("IBLOCK.ID" => 1)) // или //->setFilter(array("IBLOCK_ID" => 1)) ->setLimit(1);
Запрос:
SELECT `iblock_element_iblock`.`NAME` AS `IBLOCK_ELEMENT_IBLOCK_NAME` FROM `b_iblock_element` `iblock_element` LEFT JOIN `b_iblock` `iblock_element_iblock` ON `iblock_element`.`IBLOCK_ID` = `iblock_element_iblock`.`ID` WHERE `iblock_element_iblock`.`ID` = 1 LIMIT 0, 1
Пример #6
Runtime- может быть не только вычисляемое поле, но и ссылка на другую сущность. Т.е. в функции getMap мы можем не описывать связь, а сформировать ее прямо в запросе. Например, создадим объект Query для сущности IblockTable, свяжем ее с ElementTable и выберем элемент с ID=1:
// Query(IblockTable) $query = new \Bitrix\Main\Entity\Query(Bitrix\Iblock\IblockTable::getEntity()); $query // поле element как ссылка на таблицу b_iblock_element ->registerRuntimeField("element", array( // тип - сущность ElementTable "data_type" => "Bitrix\Iblock\ElementTable", // обратите внимание, что this.ID относится к таблице, относительно которой строится запрос // т.е. b_iblock.ID = b_iblock_element.IBLOCK_ID 'reference' => array('=this.ID' => 'ref.IBLOCK_ID'), ) ) // все поля элемента и название инфоблока ->setSelect(array("element", "NAME")) ->setFilter(array("element.ID" => 1));
Небольшая особенность — в setSelect нужно обязательно указывать runtime-поле, что добавляет в select все поля связанной таблицы.
Пример #7
В определении runtime-reference-поля можно указывать тип join’a, а в фильтре использовать сложную логику как в CIblockElement::GetList():
$query = new \Bitrix\Main\Entity\Query(Bitrix\Iblock\IblockTable::getEntity()); $query ->registerRuntimeField("element", array( "data_type" => "Bitrix\Iblock\ElementTable", 'reference' => array('=this.ID' => 'ref.IBLOCK_ID'), 'join_type' => "LEFT" ) ) ->registerRuntimeField("type", array( "data_type" => "Bitrix\Iblock\TypeTable", 'reference' => array('=this.IBLOCK_TYPE_ID' => 'ref.ID'), 'join_type' => "RIGHT" ) ) ->setSelect(array("element", "type")) ->setFilter(array( "LOGIC" => "OR", array("element.ID" => 1), array("ID" => 3) ) ) ->setLimit(2);
Пример #8
Если несколько таблиц в описании сущностей (не через runtime-поля!) связаны по цепочке, то их можно использовать в запросе через символ «.». Например, выберем ID типа инфоблока для элемента с ID=1:
$query = new \Bitrix\Main\Entity\Query(Bitrix\Iblock\ElementTable::getEntity()); $query // b_iblock_element.IBLOCK_ID = b_iblock.TYPE_ID = b_iblock_type.ID ->setSelect(array("IBLOCK.TYPE.ID")) ->setFilter(array("ID" => 1));
К сожалению, не получилось создать запрос, на который повлиял бы метод enableDataDoubling и выяснить, что можно передавать в метод setOptions. У кого есть мысли на этот счет, прошу в комментарии.
Напоследок привет от битрикса :)
/* /bitrix/modules/main/lib/entity/query.php * The most magic method. Do not edit without strong need, and for sure run tests after. */ protected function collectExprChains(QueryChain $chain, $storages = array('hidden'))
Отличная статья, было бы не плохо добавить пример с фильтрацией по свойствам элементам, я считаю это актуально пример
Максим, свойства элементов инфоблока на момент написания статьи еще были не реализованы в классах сущностей, поэтому соответствующих примеров добавить не получилось.
А че им DQL не нравится? Как раз для любителей сферических абстрактных коней в вакууме с напухшими вишнями, чтобы детей по ночам пугать :)
Это уже не ПэХаПэ — это уже перловые лиспы и не иначе :D
Кроме шуток: что в реальности это дает на практике программисту кроме бумажки в рамочке и умного вида?
Дмитрий, ORM в общем — это круто. ORM в Битриксе — это говно. Я не понимаю, про какие бумажки ты сейчас говоришь, но ООП в умелых руках помогает писать гибкие и расширяемые приложения, внося минимальные изменения в функционал. Это возможно благодаря наследованию. Это не ваши ссаные повсюду объявленые функции и скопированный во все места одинаковый код.
Оооххх … я боюсь даже подумать о таких людях, которые сами пишут ОРМ c мутабельным ООП под свои разработки. Чаще все на самописах пытаются и там все … Ну мягко говоря не до таких расширений сознания, которые может потенциально принести лавандосом потребитель, не говоря про нагрузку.
Жизненно, но непотребно из-за 15 возможностей наворачивать обертки классов и говорить по полиморфизм.
А вообще да. Но это снова выход на урвень туповатого чмощника который сидит в визивиге и не понимает зачем ему те или иные инстансы :D
Имхо.
как можно добавить DISTINCT в select ?
Алексей, подскажите, пожалуйста, а с админкой для сrm-сущностей вы уже делали? интересует спискок записей и страница детальной записи… с возможностью из редактирования и удаления
Уберите из описания DISTINCT чтобы людей не обманывать)
DISTINCT запросы делать нельзя.
DISTINCT можно делать через Bitrix\Main\Entity\ExpressionField.
Столкнулся с тем что было необходимо через ORM написать запрос MATCH AGAINST. Вот пример реализации:
$myIterator = MyTable::getList(array(
‘runtime’ => array(
new Entity\ExpressionField(’1′, ’1′),
),
‘filter’ => array(
‘=1′ => new DB\SqlExpression(’1 AND MATCH(a,b) AGAINST (?s)’, $query)
)
));
где $query — искомая строка, a,b — fulltext индекс таблицы.
Забавно, ТП сказала что анреал сделать)
http://i.imgur.com/GGWKBCU.png
Можно небольшой пример?)
удалите,пожалуйста!
удалите,пожалуйста!
Novosti
urenrjrjkvnm
news
Novyny
Ukraine
Med
coin
Есть кто дома? :)
XEvil может решить любую капчу…
XEvil.Net
Купоны, дающие скидку 45% на XEvil до 31-го января:
J2021-45-210131-fuxc8kua0cko19fg
J2021-45-210131-fuxc8kuabg5iitgq
J2021-45-210131-fuxc8kuamkola5gi
J2021-45-210131-fuxc8kuauwkex93h
J2021-45-210131-fuxc8kub60z9pqxf
J2021-45-210131-fuxc8kubecpbhout
J2021-45-210131-fuxc8kubmoy7mnpn
J2021-45-210131-fuxc8kubxs4gil6t
J2021-45-210131-fuxc8kuc64bo3m4y
J2021-45-210131-fuxc8kuch8k4hj7b
coin
urenrjrjkvnm
coin
urenrjrjkvnm
news
Cinema
urenrjrjkvnm
urenrjrjkvnm
coin
Med
urenrjrjkvnm
news
urenrjrjkvnm
coin
Novosti
urenrjrjkvnm
news
coin
Novosti
Cinema
Life
urenrjrjkvnm
urenrjrjkvnm
Med
coin
urenrjrjkvnm
Novyny
urenrjrjkvnm
coin
Cinema
Life
urenrjrjkvnm
urenrjrjkvnm
Ukraine
coin
Med
Life
Novyny
urenrjrjkvnm
urenrjrjkvnm
Novyny
Установка скважинного адаптера в Минске и области Специалисты компании «БурАвтоГрупп» — одни из наиболее опытных и профессиональных установщиков адаптера в скважине в Минске, который не только оптимизирует подачу воды в любых климатических условиях, но и позволит вам сэкономить деньги на приобретении более дорогостоящих альтернативных устройств.Скважинный адаптер. Что это такое?Скважинный адаптер — это современное универсальное изделие из латуни, которое предназначается для прокладывания труб водопровода от скважин к домам. Адаптер является единственным альтернативным заменителем дорогостоящих и громоздких кессонов. Значительная разница в стоимости заметна даже при монтаже. Сам адаптер служит для врезки в обсадную трубу. Его использование позволит круглый год пользоваться скважиной, не волнуясь о промерзании грунта. Состоит он из двух половин, одна из них статическая (крепящаяся к обсадной трубе), а вторая половина оборудована муфтой и предназначена для крепежа насосной трубы. Абсолютно все соединения герметичны и препятствуют просачиванию воды.Монтаж скважинного адаптера — порядок работ и стоиомсть
Для монтирования адаптера размером в 1 дюйм вначале производят сверление обсадной трубы. Для скважинного адаптера предусматривается коронка, а так же уплотнение из резины для фиксации. Специальным ключом адаптер помещается внутрь трубы. Далее, на глубине промерзания, работа остается исключительно за монтажником. Он уплотняет резьбу сальником, кольцом и гайкой. После этого монтажные работы по установке скважинного адаптера закончены.Использование адаптера помогает в разы облегчить работы и миновать проблемы использования кессонов, которые имеют «привычку» давать пробоины в местах сварочных швов. Помимо этого, адаптер предоставит свободный доступ к насосу в случаях поломки или его замены.
Стоит отметить, что в работе со скваженными адаптерами не может идти речь о самостоятельном монтаже. Зачастую после подобных попыток они приходят в негодность. К отсутствию необходимого давления присоединяется и нарушенная герметичность, что просто повлечет за собой лишние расходы.Стоимость монтажа скважинного адаптера в Минске и Минской области По сравнению с установкой кессона, цены на монтаж скважинных адаптеров смотрятся очень привлекательно. Пусть это вас не смущает, ведь технология адаптера и кессона отличается, что объясняет невысокую стоимость услуг по установке и обслуживанию. Кроме этого, если вы сравните ценовую политику аналогичных нам компаний, то сразу убедитесь в демократичности и лояльности цен «БурАвтоГрупп».Заказывайте установку скважинного адаптера в Минске в «БурАвтоГрупп» — наше качество работ, оперативность и приемлемые цены не оставят вас равнодушными! Также обращаем Ваше внимание, что мы оказываем услуги бурения скважин Под Ключ.
Привет дамы и господа
Обустройство скважины
Обустройство скважины – это комплекс земельных и монтажных работ, необходимых для качественного и комфортного пользования чистой водой из только что пробуренной скважины. В результате него долгожданная вода из скважины, наконец, поступает в дом. Процесс требует точных расчетов и тщательной подготовки, которую выполняют специалисты высокой квалификации, дополненной многолетним опытом в этой сфере. При обустройстве скважины компания ” БурТехСервис” ориентируется прежде всего на нужды своего заказчика, помогая выбрать оптимальный вариант, подходящий и по цели, и по цене.
Основные этапы обустройства скважины
Подготовка.
На этом этапе мы с вами уже определившись со способом обустройства скважины, а именно – подобрали соответствующее оборудование (кессон, адаптер либо оголовок). А также приготовили необходимые материалы и инструменты. При выборе способа обустройства скважины специалисты руководствуются следующими данными: глубиной и диаметром скважины, учли расход воды в разных точках участка, протяженность водопроводных труб (длиной трубопровода). Несомненно, правильная подготовка помогает предупредить возникновение возможных проблем в будущем, а также избежать дорогостоящего ремонта.
Прибытие на место монтажа. Оборудование, а также материалы и необходимые инструменты доставляются на Ваш участок.Начинаем с земляных работ. Нами подготавливается котлован при обустройстве кессоном, либо копается приямок для обустройства с адаптером. Траншея выкапывается по необходимости. Глубина при копке должна быть ниже уровня промерзания (1,5-2 метра).Далее обрезаем обсадную трубу на нужной высоте при монтаже кессона. При монтаже адаптера труба не обрезается.После этого устанавливаем кессон, либо делаем врезку в трубу скважинного адаптера.Устанавливаем также в скважину погружной насос.
Специалисты «БурТехСервис» руководствуясь данными из паспорта скважины, подбирают насос. Необходимо учесть следующие данные:
Глубину скважиныУровни воды в статике и динамикеДебит (производительность скважины)Горизонтальный перепад (уклон) высот скважиныРасстояние от самой высокой точки забора воды до уровня земли.Продолжаем монтаж. В кессон опускается и устанавливается оголовок, гидроаккумулятор, система автоматики с реле давления. На участке устанавливают летний поливочный кран.Для прокладки трубопровода к дому ранее уже выкопана траншея. В дом подводят две магистрали: одна водоподающая, вторая – для подводки электрического кабеля от насоса. При необходимости устанавливаем греющий кабель.После всех работ выполняем подключение оборудования к электричеству. Обязательно проводится проверка работы систем автоматики.Обустройство скважины завершено!
Novosti
urenrjrjkvnm
urenrjrjkvnm
Novosti
urenrjrjkvnm
urenrjrjkvnm
Novosti
Novosti
urenrjrjkvnm
urenrjrjkvnm
Novosti
Novosti
Novosti
Novosti