Laravel如何预加载登录用户专属Thread投票数据并在模型全局生效
实现方案
方案1:全局查询作用域自动追加投票字段(性能最优)
直接在Thread模型的booted方法中注册全局作用域,用户登录状态下查询Thread时会自动追加当前用户的投票类型字段,无需每次手动编写子查询逻辑。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class Thread extends Model { protected static function booted() { // 仅登录用户查询时追加投票信息 if (auth()->check()) { static::addGlobalScope('append_user_vote', function (Builder $query) { $query->addSelect([ // 可按需追加投票类型、投票ID等字段,未投票时值为null 'user_vote_type' => Vote::select('type') ->where('user_id', auth()->id()) ->whereColumn('thread_id', 'threads.id') ->limit(1) ]); }); } } // 其他模型代码 }
如果个别场景不需要该字段,可手动跳过全局作用域:
Thread::withoutGlobalScope('append_user_vote')->get();
方案2:定义当前用户专属关联关系(灵活度更高)
如果需要获取完整的投票模型实例用于后续操作,可在Thread模型中定义限定当前用户的一对一关联,还可配置自动预加载:
class Thread extends Model { // 配置自动预加载当前用户的投票关联 protected $with = ['currentUserVote']; public function currentUserVote() { return $this->hasOne(Vote::class)->where('user_id', auth()->id()); } // 其他模型代码 }
使用时直接通过关联属性访问即可:
// 判断是否投票 $hasVoted = !is_null($thread->currentUserVote); // 获取投票类型 $voteType = $thread->currentUserVote?->type;
个别场景不需要预加载时可跳过:
Thread::without('currentUserVote')->get();
选型建议
- 仅需要投票状态、类型等基础信息,优先选方案1,单SQL完成查询性能更高
- 需要对用户的投票记录做更新、删除等操作,优先选方案2,可直接操作关联模型实例
内容的提问来源于stack exchange,提问作者Hillcow
相关产品推荐
相关产品推荐

