laravel初めて5ヶ月が経ちました。
リレーション先の情報を利用して検索機能を実装するときに、少し時間を取られました。。
例えば以下のテーブル構成であったとします。
ユーザーテーブル (users_table)
id | name | |
---|---|---|
1 | user1 | user01@example.com |
2 | user2 | user02@example.com |
3 | user3 | user03@example.com |
中間テーブル (user_subject_table)
id | user_id | subject_id | score |
---|---|---|---|
1 | 1 | 1 | 75 |
2 | 1 | 2 | 100 |
3 | 1 | 3 | 90 |
4 | 2 | 1 | 60 |
5 | 2 | 3 | 80 |
6 | 3 | 1 | 60 |
7 | 2 | 3 | 20 |
科目テーブル (subjects_table)
id | name |
---|---|
1 | 数学 |
2 | 英語 |
3 | 物理 |
App\Models\*
class User extends Model
{
use HasFactory;
protected $fillable = [
'name',
'email',
];
public function subjects() {
return $this->belongsToMany('App\Models\Subjects', 'user_subject', 'user_id', 'subject_id');
}
}
class Subject extends Model
{
use HasFactory;
protected $fillable = [
'name',
];
public function users() {
return $this->belongsToMany('App\Models\User', 'user_subject', 'subject_id', 'user_id');
}
}
with関数は、EagerLoadingという機能で、発行するクエリを少なく、効率的にDBからデータを取得する仕組み。
リレーション先の情報を利用してクエリを発行したい場合、whereHasが利用できます。
whenは第一引数がnull出ない時に第二引数のクエリを実行します。
Userモデルで作成したリレーションはsubjectsでしたので、第一引数にsubjects
第二引数ではsubjects_tableを見た際のクエリです。
続けてuser_subjectを見た時のscoreの条件も含めることができます。
class UserController extends Controller
{
public function index(Request $request)
{
//リレーション定義しておく
$query = User::with('subjects',);
// 数学の点数を取得
$math_score = $request->input('math_score')
//$math_scoreがnullでなければ実行
$query->when($math_score, function ($query) use ($math_score){
$query->whereHas('subjects', function($query) {
//数学のscoreを持っているuser
$query->where('subjects.id', 1)
//かつ数学のscoreが70点以上のユーザー
$query->where('user_subject.score', '>=', 70);
});
});
このように記述すれば条件にあうuserが取得できます。
array:2 [▼
0 => User{#1 ▶︎}
1 => User{#2 ▶︎}
]
中々便利でした!!