Laravel中如何优化重复关联查询逻辑 去除冗余代码且不影响输出
方案1:提取闭包变量直接复用(改动最小,适合单场景使用)
你可以把重复的查询逻辑提前定义为闭包变量,同时优化原代码中冗余的组合条件判断,拆分后逻辑和原代码完全等价,还能减少重复代码:
// 提前定义可复用的查询过滤逻辑 $filterVoucherUtilizations = function ($query) use ($campaignId, $date_from, $date_to) { // 公共条件统一放最前面 $query->whereNotNull('voucher_id'); if ($campaignId) { $query->where('campaign_id', $campaignId); } if ($date_from && $date_to) { $query->whereDate('created_at', '>=', $date_from) ->whereDate('created_at', '<=', $date_to); } }; // 两处逻辑直接复用同一个闭包即可 $user = User::with('voucherUtilizations.voucher') ->with('voucherUtilizations', $filterVoucherUtilizations) ->withCount(['voucherUtilizations as no_of_prizes_won' => $filterVoucherUtilizations]) ->where('id', $id->id) ->first();
方案2:封装为模型本地作用域(可全局复用,符合Laravel规范)
如果这个过滤逻辑后续在其他业务场景也会用到,可以直接在VoucherUtilization模型中定义本地作用域,后续修改过滤规则只需要改一处即可:
- 先在模型中定义作用域
// app/Models/VoucherUtilization.php public function scopeFilter($query, $campaignId = null, $dateFrom = null, $dateTo = null) { $query->whereNotNull('voucher_id'); if ($campaignId) { $query->where('campaign_id', $campaignId); } if ($dateFrom && $dateTo) { $query->whereDate('created_at', '>=', $dateFrom) ->whereDate('created_at', '<=', $dateTo); } return $query; }
- 业务代码中直接调用作用域即可,Laravel 8+ 可以用箭头函数进一步简化写法:
$user = User::with('voucherUtilizations.voucher') ->with('voucherUtilizations', fn($q) => $q->filter($campaignId, $date_from, $date_to)) ->withCount(['voucherUtilizations as no_of_prizes_won' => fn($q) => $q->filter($campaignId, $date_from, $date_to)]) ->where('id', $id->id) ->first();
内容的提问来源于stack exchange,提问作者JEJ
相关产品推荐
相关产品推荐

