在 Laravel 5 中合并 'with' 和 'whereHas'
Posted
技术标签:
【中文标题】在 Laravel 5 中合并 \'with\' 和 \'whereHas\'【英文标题】:Merge 'with' and 'whereHas' in Laravel 5在 Laravel 5 中合并 'with' 和 'whereHas' 【发布时间】:2015-06-17 23:20:56 【问题描述】:我在 Laravel 5 中有这段代码,使用 Eloquent,运行良好:
$filterTask = function($query) use ($id)
$query->where('taskid', $id);
;
User::whereHas('submissions', $filterTask)->with(['submissions' => $filterTask])->get();
基本上,目标是只获取那些提交过滤后的提交的用户,其中任何一个都有。 但是,使用相同的回调函数同时运行 whereHas 和 with 方法似乎很浪费。有没有办法简化它?
谢谢。
【问题讨论】:
不,没有其他方法(使用雄辩的关系查询 ofc)。为什么会浪费? 好吧,因为我们要过滤两次提交的条件;我只是希望有一种解决方案可以使它成为一个查询而不是更多,但是@lukasgeiter 说得很清楚。 为什么这个答案票数太少? 【参考方案1】:就性能而言,您在这里无法真正优化任何东西(除非您要从 eloquent 关系转移到连接)。不管有没有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();
【讨论】:
我有这个问题两天了,现在它就像一个魅力。 你拯救了我的一天谢谢 为了便于阅读,我可能也将其重命名为withHas
我将它添加到一个特征中,我可以轻松地在我想要的所有模型中使用它。非常推荐!【参考方案2】:
我想使用静态函数扩展来自@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();
【讨论】:
但在这种情况下,您不能将其与其他查询混合使用。这应该是您必须从模型中静态调用的第一个函数,但情况并非总是如此。【参考方案3】:“macroable”方式(Laravel 5.4+)
将此添加到服务提供者的boot()
方法中。
\Illuminate\Database\Eloquent\Builder\Eloquent::macro('withAndWhereHas', function($relation, $constraint)
return $this->whereHas($relation, $constraint)->with([$relation => $constraint]);
);
【讨论】:
在 Laravel 5.8 中我必须这样做: \Illuminate\Database\Eloquent\Builder::macro('withAndWhereHas', function($relation, $constraint) return $this->whereHas($relation , $constraint)->with([$relation => $constraint]); );以上是关于在 Laravel 5 中合并 'with' 和 'whereHas'的主要内容,如果未能解决你的问题,请参考以下文章
Laravel (5.7) Eloquent Many to Many with query on双方
Laravel 5.3 使用 with() 方法预先加载关系