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

Laravel模型关联优化:研讨会门票统计方案咨询

优化方案:利用Laravel模型关联与聚合查询实现自动统计

1. 定义模型关联

首先在Seminar模型中与UserSeminarAttendance建立一对多关联:

// app/Models/Seminar.php
public function attendances()
{
    return $this->hasMany(UserSeminarAttendance::class, 'seminar_id');
}

2. 方案一:按需预加载统计(Laravel 8.37+)

如果只需要在特定请求中获取门票总数,使用withSum方法直接聚合统计,避免循环与额外查询:

// 获取单场研讨会,自动携带总门票数
$seminar = Seminar::withSum('attendances', 'num_tickets')
    ->find($seminarid);

// 若要自定义字段名(匹配你需要的`numAttendances`):
$seminar = Seminar::withSum([
    'attendances as numAttendances' => fn($query) => $query->select(DB::raw('SUM(num_tickets)'))
])->find($seminarid);

// 直接使用统计值:$seminar->numAttendances

3. 方案二:全局自动携带统计字段

如果每次请求Seminar都需要这个统计值,添加全局作用域实现自动注入:

// app/Models/Seminar.php
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

protected static function booted()
{
    static::addGlobalScope('numAttendances', function (Builder $query) {
        $query->leftJoin('user_seminar_attendances', 'seminars.id', '=', 'user_seminar_attendances.seminar_id')
              ->selectRaw('seminars.*, COALESCE(SUM(user_seminar_attendances.num_tickets), 0) as numAttendances')
              ->groupBy('seminars.id');
    });
}

之后每次查询Seminar(比如Seminar::find($seminarid)或Seminar::all()),都会自动包含numAttendances字段,无报名记录时默认值为0。

方案优势

  • 替代原代码的循环累加,直接利用数据库聚合函数SUM,性能更优
  • 避免N+1查询问题,所有数据一次SQL请求完成
  • 自动将统计值挂载到Seminar对象,无需手动赋值

内容的提问来源于stack exchange,提问作者Delmontee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:02:34