Yii2: JOIN вернулся
8 января 2014
В Active Record Yii2 вернулся JOIN
. Внутри всё значительно проще, чем было в Yii 1.1, но возможностей сильно больше.
Сразу скажу, что поддержка noSQL никуда не делась. Более того, можно в одном «запросе» выбрать JOIN-ом из нескольких SQL-таблиц, а часть связанных данных забрать, например, из MongoDB.
Отличный пример привёл ORey на англоязычном форуме:
// Выбираем MyModel с relation1 и relation2. // Все три забираем запросом с JOIN. $query = MyModel::find() ->joinWith(['relation1', 'relation2']); $countQuery = clone $query; $pages = new Pagination(['totalCount' => $countQuery->count(), 'pageSize' => 15]); $items = $query ->orderBy($sort->orders) ->offset($pages->offset) ->limit($pages->limit) // Забираем дополнительно relation3 и relation4. // Фильтровать по ним нам не нужно, так что будут // запросы вида WHERE ID IN (1,2,3,4) или аналоги // для noSQL. ->with(['relation3', 'relation4']) ->all();
Комментарии RSS по email OK
Вот это правильно, намного больше контроля получается.
Что причиной тому?
Spider, причины две:
Очень круто!
Так даже более лучше, чем в первой версии!
denis909, хочу RSS у тебя в блоге ;)
Одного не понял в приведенном примере - зачем автор использует клон $query для определения $pages вместо того, чтобы использовать тот же объект?
Андрей, один используется для запроса типа count, второй для запроса с offset и limit.
А разве, если сделать так:
результат будет другой?
В коде из master нет.
Почему бы не сделать поддержку пагинации внутри? К примеру, как в laravel.
Это бы сократило размеры кода)) Да и вообще, посмотрите на досуге Eloquent, в нем очень много полезного, что можно было бы внедрить в Yii.
Эдуард, не очень понял, что сделает такой запрос. Разобьёт по 15 записей на страницу? Выберет 15 записей? С какой страницы?
Запрос вернет 15 записей. Примерно внутри он может выглядеть
Или, как вариант, он может возвращать класс, какой-нибудь PaginationCollection вида
И уже в PaginationCollection реализовать получение ссылок, получение результата выборки через магические методы т.д.
Выглядит как плохая идея. Модель не должна работать с запросом напрямую.
Ну это я, как пример сделал. просто так намного удобнее было было пользоваться, чем отдельно писать два запроса + создавать пагинацию. Вроде не много, всего несколько лишних строк, но ведь можно их и сократить до одного метода. А как уже его реализовать, какой там будет слой абстракции и т.д. это совершенно другой вопрос, тут Вам виднее ))
Александр, а как вам немного другая идея реализации? метод paginate в моделе выглядит так:
А класс PaginationCollection работает с запросами. Вот весь код класса pastebin.com/J4WpeJdK, он имплементирует ArrayAccess и Iterator. Пользоваться можно, как и прежде
Я не думаю, что работу с реквестом стоит тащить в модель.
А что если
MyModel
иrelation1
имеют одинаковые названия колонок? Напримерname
. Тогда ведь при JOIN будет подгружено*
, иname
изrelation1
перезапишет в массиве, что используется вpopulate()
,name
изMyModel
. Верно?ого, только что увидел, а всего пару лет прошло ) sam, сделаю на досуге!
Большое подозрение что joinWith не имеет никакого смысла поскольку в запрос кострукция JOIN добавляется, но в SELECT выгребаются только поля первой таблицы, которая указанна в блоке FROM.
А relations потом набираются в методе \yii\db\ActiveQuery.populate, отдельным запросом
Подробнее описал на форуме yiiframework.ru/forum/viewtopic.php?f=19&t=36147
Почему не имеет? Для фильтрации очень даже имеет.
Sam, с помощью AR я могу получить данные из связанных таблиц одним запросом?
Пока я для этого использую join из Query
Нет.
$users = \app\models\ActiveRecord\User::find() ->select($fields) ->joinWith('announce', true) ->where(['user_id' => $this->user_id]) ->asArray()->all();
так выводит поля из всех связанных таблиц