6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】リレーション先のデータを条件指定して取得する

Posted at

やりたいこと

例えば usersテーブルとblogsテーブルが1対多の関係にあり、全てのユーザー情報と、ユーザーが書いたブログのうちcategoryがPHPのブログ情報をまとめて取得したい、というような場面。

Laravelでは User::with('blogs') のように記述することでリレーション先のテーブルのデータもまとめて取得することが出来るが、その際に取得するリレーション先のデータの条件指定の方法について、備忘録としてまとめておく。

記述方法

結論、以下の記述でやりたいことが実現できる。

$items = User::with(['blogs' => function ($query) {
	$query->where('category', 'PHP');
}])->get();

実行しているSQLを出力して確認してみる。

DB::enableQueryLog();

$items = User::with(['blogs' => function ($query) {
	$query->where('category', 'PHP');
}])->get();

Log::debug(DB::getQueryLog());

SQL出力結果

array (
  0 => 
  array (
    'query' => 'select * from `users`,
    'bindings' => 
    array (
    ),
    'time' => 9.9,
  ),
  1 => 
  array (
	    'query' => 'select * from `blogs` where `blogs`.`user_id` in (1, 2, 3, ...省略

上記の通り、ユーザー情報は全て取得し、ブログについてはcategoryがPHPのもののみ取得できていることが分かる。

失敗例

ちなみに以下の書き方だと、whereHasの条件に合うユーザー情報を取得する。

よって今回のように、ユーザー情報は全て取得したうえで、リレーション先のデータは指定した条件に合うものだけ取得したい、、という場合は以下の書き方ではいけないので注意。

$items = User::with(['blogs'])->whereHas('blogs', function ($query) {
	$query->where('category', 'PHP');
}])->get();

こちらも実行しているSQLを出力して確認してみる。

DB::enableQueryLog();

$items = User::with(['blogs'])->whereHas('blogs', function ($query) {
	$query->where('category', 'PHP');
}])->get();

Log::debug(DB::getQueryLog());

SQL出力結果

array (
  0 => 
  array (
    'query' => 'select * from `users` where exists (select * from `blogs` where `users`.`id` = `blogs`.`user_id` and `category` = ?),
    'bindings' => 
    array (
      0 => 'PHP',
    ),
    'time' => 20.21,
  ),
  1 => 
  array (
    'query' => 'select * from `blogs` where `blogs`.`user_id` in (1, 4, 5, ...省略

上記の通り、existsでサブクエリを使って、リレーション先で指定した条件に合致するユーザー情報とそのリレーション先のデータを取得していることが分かる。

さいごに

実行されているSQLを確認すると、何が起きているのか分かりやすかった。

普段からEloquentを使うときにはどのようなSQLが実行されるのか把握し、SQLの実行計画も確認して重くなっていないか意識するようにしたい。

参考記事

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?