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

如何用Eloquent优雅实现关联表求和并按结果排序?

用Laravel Eloquent优雅实现按关联分数总和排序用户列表

首先得揪个小细节:你的Score模型类名写错成Job啦,先把这个修正过来,不然关联逻辑会出问题:

class Score extends Model {
    // 可以补充定义反向关联,让模型关系更完整
    public function user() {
        return $this->belongsTo('App\User');
    }
}

回到你的核心需求:摆脱foreach循环,用更优雅的Eloquent写法实现用户列表按关联分数总和降序排列。原来的写法会触发N+1查询问题(先查所有用户,再循环每个用户单独查分数总和),而我们可以直接在数据库层面完成聚合计算和排序,既简洁又高效。

优化后的控制器代码

$users = User::withSum('scores', 'score')
    ->orderByDesc('scores_sum_score')
    ->get();

return view('homepage', [
    'users' => $users
]);

代码说明

  • withSum('scores', 'score'):Eloquent的这个方法会自动为每个用户计算关联scores表中score字段的总和,结果会存储在scores_sum_score属性中(命名规则是关联名_sum_字段名)
  • orderByDesc('scores_sum_score'):直接在数据库层面按分数总和降序排序,比在PHP集合中排序性能提升明显
  • 最终每个$user对象都会自带scores_sum_score属性,你可以在视图里直接用{{ $user->scores_sum_score }}展示总和

如果想给总和字段起个更贴合需求的名字(比如score_sum),可以用自定义字段名的写法:

use Illuminate\Support\Facades\DB;

$users = User::withSum(
    ['scores' => fn($query) => $query->select(DB::raw('sum(score) as score_sum'))],
    'score'
)
->orderByDesc('score_sum')
->get();

这样每个用户对象的属性就变成score_sum,和你预期结果里的字段名完全匹配。

这种方式只需要1次数据库查询,既避免了循环带来的冗余查询,代码也更符合Laravel Eloquent的优雅风格~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:26:34