Laravel Eloquent关联查询:按Reservation的type筛选Jump数据
问题:Eloquent关联筛选无效的解决办法
原始查询代码
$cameras=Jump::Video() ->with('flight','flight.aircraft','flight.airfield') ->with('student','student.logininfo','student.logininfo.reservations') ->with('camera','camera.status') ->whereBetween('data',[ $from, $to]) ->orderBy($sortBy, $orderDesc) ->paginate($request->perPage);
模型关联关系
Jump.php
public function scopeVideo($query) { return $query->where('exercise', '104'); } public function student() { return $this->hasOne('App\Models\PersonalData','id','student'); }
PersonalData.php
public function logininfo() { return $this->hasOne('App\User','id_user','id'); }
User.php
public function reservations() { return $this->hasMany('App\Models\Reservation','user_id', 'id'); }
需求与尝试的无效写法
需求:仅获取关联Reservation表中type字段等于$request->type的Jump数据。
尝试的两种无效写法:
- 直接查询关联字段(错误用法):
->where('student.logininfo.reservations','=',$request->type)
- 点语法的whereHas(未生效):
->whereHas('student.logininfo.reservations',function($query) use ($request) { return $query->where('type','=',$request->type) })
解决办法
正确的筛选写法
写法一:嵌套whereHas(层级清晰,适合复杂关联)
$cameras=Jump::Video() ->with([ 'flight.aircraft', 'flight.airfield', 'student.logininfo.reservations', 'camera.status' ]) ->whereBetween('data',[ $from, $to]) ->whereHas('student', function ($query) use ($request) { $query->whereHas('logininfo', function ($query) use ($request) { $query->whereHas('reservations', function ($query) use ($request) { $query->where('type', $request->type); }); }); }) ->orderBy($sortBy, $orderDesc) ->paginate($request->perPage);
写法二:点语法whereHas(简洁写法)
$cameras=Jump::Video() ->with([ 'flight.aircraft', 'flight.airfield', 'student.logininfo.reservations', 'camera.status' ]) ->whereBetween('data',[ $from, $to]) ->whereHas('student.logininfo.reservations', function($query) use ($request) { $query->where('type', $request->type); }) ->orderBy($sortBy, $orderDesc) ->paginate($request->perPage);
无效原因排查
- 第一种写法完全错误:
student.logininfo.reservations是Eloquent关联关系,不是数据库表字段,不能直接用where查询。 - 第二种写法本身语法正确,未生效可能是以下原因:
$request->type未传递有效值,可先通过dd($request->type)验证;- 模型关联的外键设置错误,比如
PersonalData的logininfo关联中,id_user与id的对应关系是否和数据库字段匹配; - 数据链断裂:部分Jump没有关联的student,或student没有logininfo,或logininfo没有符合条件的reservations;
- 闭包末尾遗漏分号(你提供的代码里确实少了分号)。
额外优化
将多个with()调用合并为一个数组参数,代码更简洁易读,如上述写法所示。
内容的提问来源于stack exchange,提问作者Sebastian Dratwa
相关产品推荐
相关产品推荐

