こんにちは!
見出しは、なんか某アニメ映画のタイトルみたいなになっていますが、、、
要は、Laravelでリレーションを組んでいた場合、主テーブルに紐付いている従テーブルを絞り込むか、従テーブルを元に主テーブルを絞り込むか、の解説をしていきます。
主テーブル・・・・・主キー(id)を持つテーブル
従テーブル・・・・・外部キー(***_id)を持つテーブル
今回は例として、
ゲーム情報を取得時に、特定のユーザーが登録しているゲームのお気に入り情報を取得する場合 (withメソッドを使う)
ゲーム情報を取得時に、特定のユーザーがお気に入りをしているゲームを取得 (whereHasメソッドを使う)
というケースを考えます。
目次
環境
今回の環境
- PHP 8.1.1
- Laravel 9.19
テーブル構造
記事用なので簡潔に書きます。
ゲーム一覧テーブル (game)
ゲーム一覧を管理するテーブルになります。
カラム名 | データ内容 | FK |
id | ID | |
game_name | ゲーム名 |
ゲームお気に入りテーブル (favorite)
ゲームをお気に入りした場合、このテーブルにレコードが追加されます。
カラム名 | データ内容 | FK |
id | ID | |
game_id | ゲームID | ○ |
user_id | ユーザーID | ○ |
ユーザーテーブル (users)
ユーザーを管理するテーブルになります。
カラム名 | データ内容 | FK |
id | ID | |
name | ユーザー名 |
モデルファイル
ゲーム一覧モデル
ゲームモデルに、ゲームお気に入りモデルのリレーションを設定します。
ゲームは、いろんなユーザーがお気に入り登録できるので、1対多
の関係になります。
public function favorite()
{
return $this->hasMany('App\Models\FavoriteGames');
}
リレーション先を絞り込む場合
リレーション先を絞り込む(主テーブルに紐付いている従テーブルを絞り込む)場合を見ていきます。
例えば、特定のユーザーのお気に入り情報が欲しい場合、リレーション先である、お気に入りテーブルのuser_id
を絞り込む必要があります。
その場合、以下のようにwith
メソッドの中でクロージャーを使います。
Games::with(['favorite' => function ($query) use ($user_id) {
$query->where('user_id', $user_id);
}])->where('id', $game_id)->first();
実際にゲームid=1
のゲーム取得時に、ユーザーid=2
のお気に入り情報のみを取得したい場合は、以下のようになります。
>>> Games::with(['favorite' => function ($query) {
$query->where('user_id', 2);
}])->where('id', 1)->first();
=> App\Models\Games {#3687
id: 1,
game_name: ファイナルファンタジー
favorite: Illuminate\Database\Eloquent\Collection {#4831
all: [
App\Models\FavoriteGames {#4226
id: 2,
games_id: 1,
user_id: 2,
},
],
},
}
with
メソッドのクロージャー内で、user_id
を絞らないと、そのゲームお気に入り登録しているすべてのユーザー情報も取得してしまいます。
>>> Games::with(['favorite'])->where('id', 1)->first();
=> App\Models\Games {#3687
id: 1,
game_name: ファイナルファンタジー
favorite: Illuminate\Database\Eloquent\Collection {#4831
all: [
App\Models\FavoriteGames {#4224 => ここユーザーの情報入らない
id: 1,
games_id: 1,
user_id: 1,
},
App\Models\FavoriteGames {#4226
id: 2,
games_id: 1,
user_id: 2,
},
],
},
}
リレーション先で絞り込む場合
次にリレーション先で絞り込む(従テーブルを元に主テーブルを絞り込む)場合を見ていきます。
今回の場合、特定のユーザーが、お気に入りをしているゲームのみ取得したい場合、になります。
その場合、以下のようにwhereHas
メソッドを使います。
Games::whereHas('favorite', function ($query) use ($user_id) {
$query->where('user_id', $user_id);
});
実際に、ユーザーid=2がお気に入り登録しているゲームを取得してみます。
>>> Games::whereHas('favorite', function ($query) {
$query->where('user_id', 2);
})->get();
=> Illuminate\Database\Eloquent\Collection {#3697
all: [
App\Models\Games {#3708
id: 60,
game_name: "ポケモン",
},
App\Models\Games {#3680
id: 61,
game_name: "デジモン",
},
App\Models\Games {#3715
id: 62,
game_name: "フジモン",
},
],
}
以上になります。