我在Laravel 5中有这个代码,使用Eloquent,它运行得很好:
$filterTask = function($query) use ($id) {
$query->where('taskid', $id);
};
User::whereHas('submissions', $filterTask)->with(['submissions' => $filterTask])->get();
基本上,我们的目标是只为那些拥有过滤提交的用户提供服务。 但是,使用相同的回调函数运行 whereHas 和 with 方法似乎浪费了。有没有办法简化它?
感谢。
答案 0 :(得分:32)
在性能方面,你可以在这里真正优化任何东西(除非你要从雄辩的关系转变为联接)。无论有没有whereHas
,都会运行两个查询。一个选择所有用户另一个加载相关模型。当您添加whereHas
条件时,会添加子查询,但它仍然是两个查询。
但是,从语法上来说,你可以通过向模型添加query scope来优化这一点(如果你想更频繁地使用它,甚至可以添加基础模型):
public function scopeWithAndWhereHas($query, $relation, $constraint){
return $query->whereHas($relation, $constraint)
->with([$relation => $constraint]);
}
用法:
User::withAndWhereHas('submissions', function($query) use ($id){
$query->where('taskid', $id);
})->get();
答案 1 :(得分:1)
“ 可宏”方式( Laravel 5.4 + )
将其添加到服务提供商的boot()
方法中。
\Illuminate\Database\Eloquent\Builder\Eloquent::macro('withAndWhereHas', function($relation, $constraint){
return $this->whereHas($relation, $constraint)->with([$relation => $constraint]);
});
答案 2 :(得分:0)
我想使用静态函数扩展@lukasgeiter的答案。
public static function withAndWhereHas($relation, $constraint){
return (new static)->whereHas($relation, $constraint)
->with([$relation => $constraint]);
}
用法相同
User::withAndWhereHas('submissions', function($query) use ($id){
$query->where('taskid', $id);
})->get();