You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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模型中定义本地作用域,后续修改过滤规则只需要改一处即可:

  1. 先在模型中定义作用域
// 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;
}
  1. 业务代码中直接调用作用域即可,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 03:15:05