Laravel ORM如何按子模型投票总数对选项排序?
实现方案
1. 确认模型关联定义
先确保三个模型的关联关系配置正确:
Issue 模型(app/Models/Issue.php)
class Issue extends Model { // 关联当前议题下的所有选项 public function options() { return $this->hasMany(Option::class); } }
Option 模型(app/Models/Option.php)
class Option extends Model { // 关联当前选项下的所有投票记录 public function votes() { return $this->hasMany(Vote::class); } }
Vote 模型(app/Models/Vote.php)
class Vote extends Model { // 关联投票所属的选项 public function option() { return $this->belongsTo(Option::class); } }
2. 实现选项按投票数降序加载
有两种实现方式,可根据业务场景选择:
方式一:查询时动态指定排序(适合仅特定页面需要排序的场景)
在控制器查询议题数据时,通过预加载关联的方式,统计每个选项的投票数并按降序排序:
$issues = Issue::with(['options' => function ($query) { // 统计投票数并按降序排列选项 $query->withCount('votes')->orderBy('votes_count', 'desc'); }])->get();
方式二:关联中默认排序(适合所有场景都需要按投票数排序的情况)
直接在Issue模型的options关联中加入统计和排序逻辑,后续每次加载选项都会自动按投票数降序排列:
public function options() { return $this->hasMany(Option::class) ->withCount('votes') ->orderBy('votes_count', 'desc'); }
此时控制器只需正常查询即可:
$issues = Issue::with('options')->get();
3. Blade模板遍历显示
模板中直接遍历$issues即可,每个议题下的选项已经按投票数降序排列,votes_count是withCount自动生成的统计属性:
@foreach($issues as $issue) <div class="issue-container"> <h3>{{ $issue->title }}</h3> <div class="options-list"> @foreach($issue->options as $option) <div class="option-item"> <span>{{ $option->content }}</span> <span class="vote-num">投票数:{{ $option->votes_count }}</span> </div> @endforeach </div> </div> @endforeach
补充说明
withCount()是Laravel ORM提供的高效统计方法,自动生成统计字段并避免N+1查询问题- 如果需要实时更新投票数(比如投票后无需刷新页面),可以结合AJAX更新前端数据,ORM层面的排序逻辑无需改动
内容的提问来源于stack exchange,提问作者luisfer
相关产品推荐
相关产品推荐

