APIドキュメントでは、
$joinWith
-このクエリが持つべきリレーションのリストjoined with$with
-このクエリが持つべきリレーションのリスト実行
これらのActiveQueryプロパティの違いは何ですか?また、どのような状況で$joinWith
および$with
?
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
を使用しています。
doc -> http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#joining-with-relations は、この:
"リレーショナルデータベースを使用する場合、一般的なタスクは複数のテーブルを結合し、JOIN SQLステートメントにさまざまなクエリ条件とパラメーターを適用することです。yii\ db\ActiveQuery :: join()を明示的に呼び出す代わりにJOINクエリを作成し、既存のリレーション定義を再利用し、yii\db\ActiveQuery :: joinWith()を呼び出してこの目標を達成できます。 "
つまり、joins
、innerJoins
、outerJoins
、およびYii2の関連するすべてのものを自分で処理できるようになりました。 Yii(Yii2ではない)は、ユーザーに結合のタイプを決定させることなく、代わりにjoin
のみを使用します。 「結合」の詳細-> SQLベースのもの。これについてはこちらをご覧ください http://en.wikipedia.org/wiki/Join_(SQL)
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
を使用する場合、リレーション別にby/filter/groupを並べ替えることができます。自分で列名を明確にする必要がある場合があります。
参照: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#lazy-eager-loading
上記の素晴らしい回答に加えて、joinWith()
の使用方法を理解するのに役立ちました。また、joinWith()
を使用したいときに、曖昧な列名がある場合は、Yii/ActiveRecordは、通常期待するもの(左端のテーブル)ではなく、自動的にランダムな列を選択するようです。何かを指定することにより、SELECT
句で左端のテーブルを指定するのが最善です$query->select("post.*")
のように、いくつかの内部テーブルからidを取得していましたが、それらを理解するまで、左端のテーブルからwereのように使用されていました。
もう1つの注意点は、can joinwith関係のエイリアスを指定することです。したがって、次のように言えます。
$post->find()
->joinWith(["user u"])
->where(["u.id"=>$requestedUser->id])
->select("post.*")
->orderBy(["u.created_at"=>SORT_DESC]);