Laravel中get()后调用where()的代码是否可行?实际作用是什么?
聊聊这段Laravel代码的可行性与实际作用
嘿,我来帮你拆解这段代码的问题,先给你明确结论:这段代码是能运行的,但写法存在明显的性能问题,而且逻辑细节需要注意。
一、为啥这代码能跑?
你疑惑的where('product.name', 'GAP Insurance')不是数据库层面的SQL查询,而是Laravel集合(Collection)的内存过滤方法。具体流程是这样的:
- 先执行SQL:从
policies表查出leadID等于$leadId、且policystatus不是Canceled的所有记录,用get()把结果转成Laravel集合。 - 接着调用集合的
where()方法,在内存里过滤那些关联的product模型的name等于"GAP Insurance"的项。 - 最后统计符合条件的数量是否大于1,把结果赋值给
$hasGAP。
这里有个前提:你的Policy模型肯定已经定义了和Product模型的关联(比如写了public function product() { return $this->belongsTo(Product::class); }),Laravel会用延迟加载的方式,当你访问集合里保单的product属性时,自动去查对应的产品数据。
二、它实际想做啥?
这段代码的核心意图很明确:判断当前$leadId对应的客户,有没有至少2条没取消的、关联产品是GAP Insurance的保单。如果符合条件的保单数大于1,$hasGAP就是true,否则是false。
三、这段代码的坑在哪?
虽然能运行,但绝对不推荐这么写,主要有两个问题:
- N+1查询灾难:因为用了延迟加载,集合里有多少条保单,就会多执行多少次查询去拉产品数据,数据量一大,性能直接崩。
- 内存浪费:先把所有未取消的保单全查出来塞进内存,再过滤,完全可以在数据库层面直接完成筛选,既省内存又快。
四、更优的写法参考
要实现同样的逻辑,应该用Laravel的关联查询,把过滤条件放到SQL层面,只查需要的数据:
$hasGAP = \App\Models\Policy::where('leadID', $leadId) ->where('policystatus', '!=', 'Canceled') ->whereHas('product', function ($query) { $query->where('name', 'GAP Insurance'); }) ->count() > 1;
这样只会执行一次SQL查询,所有筛选都在数据库里完成,性能和内存占用都能提升一大截。
内容的提问来源于stack exchange,提问作者neubert
相关产品推荐
相关产品推荐

