Laravel 7:如何优化排除客户已选服务的查询逻辑?
Laravel 查询逻辑优化:排除客户已关联服务
原问题背景
Measurement 表结构
| id | customer_id | service_id |
|---|---|---|
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 2 | 2 |
原控制器代码
$customer = Customer::findOrFail($id); $ex = Measurement::where('customer_id', $id)->pluck('service_id'); if(count($ex) == 0){ $service = Service::where('status', 0)->get(); } else{ $service = Service::where('id', '!=', $ex)->where('status', 0)->get(); }
原逻辑:客户无关联service_id时返回所有status=0的服务;有则返回排除已关联ID且status=0的服务。
优化实现方案
方案一:简化条件判断,修复多值排除逻辑
原代码中where('id', '!=', $ex)存在逻辑问题——当$ex是多ID集合时,!=无法正确处理多值排除,改用whereNotIn,同时用Laravel的when()方法替代分支判断,让代码更简洁:
$customer = Customer::findOrFail($id); // 过滤空的service_id,避免无效值干扰查询 $excludedIds = Measurement::where('customer_id', $id) ->whereNotNull('service_id') ->pluck('service_id'); $services = Service::where('status', 0) ->when($excludedIds->isNotEmpty(), function ($query) use ($excludedIds) { $query->whereNotIn('id', $excludedIds); }) ->get();
方案二:利用模型关联简化代码(需提前定义关联)
如果Customer模型已和Measurement模型定义关联:
// Customer.php public function measurements() { return $this->hasMany(Measurement::class); }
可以直接通过关联获取排除ID,代码更直观:
$customer = Customer::findOrFail($id); $excludedIds = $customer->measurements() ->whereNotNull('service_id') ->pluck('service_id'); $services = Service::where('status', 0) ->when($excludedIds->isNotEmpty(), fn($q) => $q->whereNotIn('id', $excludedIds)) ->get();
优化点说明
- 修复多值排除逻辑:用
whereNotIn替代!=,正确处理多个ID的排除需求 - 过滤无效值:增加
whereNotNull('service_id'),避免将Measurement表中为空的service_id作为排除条件 - 简化代码结构:用
when()方法替代if-else分支,让查询逻辑连贯易读
内容的提问来源于stack exchange,提问作者Farlar
相关产品推荐
相关产品推荐

