В чем разница между $with и $joinWith в Yii2 и когда их использовать?


В документации API указано, что

  • $joinWith - Список отношений, которые этот запрос должен соединить с
  • $with - Список отношений, с которыми этот запрос должен быть выполнен с

В чем разница между этими свойствами ActiveQuery и в какой ситуации мы должны использовать $joinWith и $with?

 28
Author: lin, 2014-09-01

3 answers

Разница между with и joinWith

Использование метода with приводит к следующим SQL-запросам

$users = User::find()->with('userGroup');

SELECT * FROM `user`;
SELECT * FROM `userGroup` WHERE userId = ...

... в то время как использование joinWith приведет к этому SQL-запросу

$users = User::find()->joinWith('userGroup', true)

SELECT * FROM user LEFT JOIN `userGroup` userGroup ON user.`id` = userGroup.`userId`;

Поэтому я использую joinWith, когда мне нужно фильтровать или искать данные в связанных таблицах.

Дополнительная информация

Документ -> http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#joining-with-relations расскажу вам об этом:

" При работе с реляционными базами данных общей задачей является объединение нескольких таблиц и применение различных условий и параметров запроса к инструкции SQL JOIN. Вместо явного вызова yii\db\ActiveQuery::join() для создания запроса на объединение, вы можете повторно использовать существующие определения отношений и вызвать yii\db\ActiveQuery::joinWith() для достижения этой цели."

Это означает, что вы способны справиться joins, innerJoins, outerJoins и все хорошие связанные с этим вещи в Yii2 по теперь ты сам. Yii (не Yii2) использует только join вместо этого, не позволяя пользователю решать о типе соединения. Подробнее о "Присоединении" -> это вещь, основанная на SQL. Вы можете прочитать об этом здесь http://en.wikipedia.org/wiki/Join_ (SQL)

 20
Author: lin, 2017-01-03 11:18:14

joinWith использует JOIN для включения отношений в исходный запрос, в то время как with этого не делает.

Для дальнейшей иллюстрации рассмотрим класс Post с отношением comments следующим образом:

class Post extends \yii\db\ActiveRecord {
    ...
    public function getComments() {
        return $this->hasMany(Comment::className(), ['post_id' => 'id']);
    }
}

Используя with приведенный ниже код:

$post = Post::find()->with('comments');

Приводит к следующим sql-запросам:

SELECT `post`.* FROM `post`;
SELECT `comment`.* FROM `comment` WHERE post_id IN (...)

В то время как код joinWith ниже:

$post = Post::find()->joinWith('comments', true)

Результаты в запросах:

SELECT `post`.* FROM post LEFT JOIN `comment` comments ON post.`id` = comments.`post_id`;
SELECT `comment`.* FROM `comment` WHERE post_id IN (...);

В результате при использовании joinWith вы можете упорядочивать/фильтровать/группировать по отношению. Вы можете вам придется самостоятельно устранять неоднозначность в названиях столбцов.

Ссылка: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#lazy-eager-loading

 32
Author: topher, 2017-10-09 07:26:03

Пожалуйста, обратите внимание, что в дополнение к приведенным выше удивительным ответам, которые помогли мне понять, как использовать joinWith(), что всякий раз, когда вы хотите использовать joinWith() и у вас неоднозначные имена столбцов, Yii/ActiveRecord автоматически выбирает случайный столбец вместо того, что вы обычно ожидаете (крайняя левая таблица). Лучше всего указать крайнюю левую таблицу в предложении SELECT, указав что-то вроде $query->select("post.*"). Я получал идентификаторы из некоторых внутренних таблиц, и они использовались так, как будто они были с крайнего левого стола, пока я не понял это.

Еще один момент, который следует отметить, заключается в том, что вы можете указать псевдоним для отношения joinwith, чтобы вы могли сказать что-то вроде:

$post->find()
->joinWith(["user u"])
->where(["u.id"=>$requestedUser->id])
->select("post.*")
->orderBy(["u.created_at"=>SORT_DESC]);
 0
Author: Dhiraj Gupta, 2018-01-08 16:13:03