Laravel Orm一对多关联查询

新手上路,请多包涵

假设主表是班级Class,副表是学生Student。 建立一对多关系后,可以轻松得到各班级包含的学生。
按条件筛选,如果是基于主表Class的,比如只看英语班的学生,查询可以是Class::with(['student'])->where("班级类型","英语")->get();

但是如果是基于副表Student的筛选条件,比如有几个班全是女学生,现在只查询男学生所在班级和学生信息,这么写:
Class::with(['student'=>function($query){

$query->where("学生性别","男");

}])->get();
则查询的结果会先执行select * from Class; 还是会返回有女学生的班级(只是没有Student学生数据),然后在符合副表筛选条件的Class下充填Student数据。

而我希望返回的结果只是男学生所在的Class和Student信息

加上whereHas后:
Class::whereHas('student',function($query){

        $query->where("学生性别","男");
   })->with(['student'=>function($query){
$query->where("学生性别","男");

}])->get();

如果这么写,倒是可以只返回男学生所在的Class和Student信息

可是这样是不是比较麻烦了,需要把副表的筛选条件在whereHas和with里都要写一遍,有没有更加优雅的Orm写法呢? 若是使用DB的join则简单许多了吧?

阅读 2.9k
1 个回答

whereHas 是一个前置条件,用来确保,在查询出来的 Class 一定是符合 where 的条件的,而 with 方法才是最终查询 Student 时使用到的,所以存在在这个问题。

其次,更加建议使用 join 来处理类似的问题,因为 whereHas 会使用子查询来处理,存在一些性能问题。

当然,你也可以坚持使用 whereHas + with 的方式,你把你那一个查询的匿名函数声明成变量就好了。

$filter = function ($query) {
    $query->where('学生性别', '男');
};

Classes::whereHas('student', $filter)
    ->with(['student' => $filter,])
    ->get();
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏