Laravel Eloquent同模型关联查询结果能否复用?
解决Eloquent同模型关联重复查询的问题
Eloquent默认会为每个关联独立执行预加载查询,即使两个关联(如author和submitter)指向同一个User ID,也会触发重复查询。要实现查询结果复用,可通过以下几种方式优化:
方法一:手动处理批量预加载(推荐)
针对批量查询场景,先收集所有涉及的用户ID,一次性查询后手动绑定关联关系,彻底避免重复查询:
// 查询目标文章集合 $posts = Post::whereIn('id', [1, 2])->get(); // 收集所有作者和提交者的ID并去重 $userIds = $posts->flatMap(function ($post) { return [$post->user_id, $post->submitter_id]; })->unique()->values(); // 一次性查询所有需要的用户,按ID分组便于快速匹配 $users = User::find($userIds)->keyBy('id'); // 为每篇文章手动设置关联 $posts->each(function ($post) use ($users) { $post->setRelation('author', $users[$post->user_id]); $post->setRelation('submitter', $users[$post->submitter_id]); });
这种方式不管ID是否重复,都只会执行一次用户查询,性能最优。
方法二:单篇文章的延迟加载优化
如果仅查询单篇文章,可先加载作者关联,再判断提交者ID是否与作者一致,一致则直接复用作者模型:
$post = Post::find($id); $post->load('author'); if ($post->user_id === $post->submitter_id) { $post->setRelation('submitter', $post->author); } else { $post->load('submitter'); }
方法三:自定义预加载方法(全局复用)
在Post模型中封装自定义预加载逻辑,方便全局调用:
class Post extends Model { protected $guarded = []; public function author() { return $this->belongsTo(User::class); } public function submitter() { return $this->belongsTo(User::class, 'submitter_id'); } // 自定义预加载方法 public static function withAuthorAndSubmitter() { return static::with(['author'])->get()->each(function ($post) { if ($post->user_id === $post->submitter_id) { $post->setRelation('submitter', $post->author); } else { $post->load('submitter'); } }); } } // 使用方式 $posts = Post::withAuthorAndSubmitter();
内容的提问来源于stack exchange,提问作者Sᴀᴍ Onᴇᴌᴀ
相关产品推荐
相关产品推荐

