やりたいこと
リレーションの先で条件検索はありましたが、先の先が中々見当たらなかったのでメモ代わりに記載しました。
Laravel Eloquentで取得していきます。
例えば usersテーブルとproductsテーブルが1対多の関係にあり、さらにproductsテーブルとblogsテーブルが1対多の関係にある場合にblogsテーブル→productsテーブル→usersテーブルのusersの名前で条件をつけたい場合の記法です。
※あくまでも例なのでテーブルの内容やDBの構造は気にしないでください。
動作環境
Laravel9.0
記述方法
結論、以下の記述でやりたいことが実現できる。
$userId = 1; //usersテーブルのid = 1が条件
$items = Blog::wereHas(['product', function($query) use($userId) {
$query->wereHas('user', function($query) use($userId) {
$query->where('id', $userId);
});
}])->get();
実行しているSQLを出力して確認してみる。
use($xxxx)で変数を持っていかないとエラーになる。
blogsテーブル→productsテーブル→usersのつまり
usersの条件を元に検索をかける。
主なデータ
主なデータは以下に記載の通りです。
Userテーブル
id | name |
---|---|
1 | 田中 |
2 | 鈴木 |
3 | 佐藤 |
Productテーブル
id | name | user_id |
---|---|---|
1 | スポーツ | 1 |
2 | 読書 | 2 |
3 | 仕事 | 3 |
Blogテーブル
id | name | product_id |
---|---|---|
1 | title1 | 1 |
2 | title2 | 2 |
3 | title3 | 3 |
...省略
public function users()
{
$this->hasMany('App\Models\Product');
}
...省略
public function user()
{
$this->belongsTo('App\Models\User');
}
public function blogs()
{
$this->hasMany('App\Models\Blog');
}
...省略
public function product()
{
$this->belongsTo('App\Models\Product');
}
上記の通り、ユーザー情報は全て取得し、ブログについてはcategoryがPHPのもののみ取得できていることが分かる。
失敗例 & 成功例
以下の書き方だと、whereHasの条件に合うユーザー情報を取得する。
今回のように、blogs情報は全て取得したうえで、リレーション先のその先のデータを指定した条件に合うものだけ取得したい、、という場合は以下の書き方ではいけないので注意。
use($userId)がないとエラーになる
//失敗例
$userId = 1; //usersテーブルのid = 1が条件
$items = Blog::wereHas(['product', function($query) {
$query->wereHas('user', function($query) {
$query->where('id', $userId);
});
}])->get();
//成功例
$userId = 1; //usersテーブルのid = 1が条件
$items = Blog::wereHas(['product', function($query) use($userId) {
$query->wereHas('user', function($query) use($userId) {
$query->where('id', $userId);
});
}])->get();
上記の通り、use($userId)がないとエラーになる
ので注意
さいごに
この記法でさらに先までも検索は可能だと思います。