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
相关产品推荐
相关产品推荐

