Laravel Eloquent加载关联模型时如何自动设置双向关联关系
解决方案
Laravel 原生内置了对应能力,不需要手动遍历集合绑定关联,也不需要冗余预加载,直接在hasMany关联定义上调用withInverse()方法指定反向关联名即可。
修改Thread模型的posts关联定义:
class Thread extends Model { public function posts() { return $this->hasMany(Post::class)->withInverse('thread'); } }
加完这行配置后,框架会在你通过Thread实例加载关联Post时,自动把当前Thread实例注入到每一个Post模型的thread关联对象中,完全匹配你的预期效果:
- 执行
$posts->first()->thread === $thread会直接返回true - 调用
$thread->posts->toArray()时,Post模型的getTitleAttribute访问器读取$this->thread会直接使用已经注入的关联实例,不会为每个Post单独发起查询Thread的SQL,从根源上避免了N+1问题。
注意事项
withInverse()是Laravel 5.4及以上版本自带的关联方法,无需安装额外扩展- 方法传入的参数是Post模型中定义的反向belongsTo关联的方法名,如果你Post模型里的反向关联方法不叫
thread,替换成对应方法名即可 - 该逻辑仅在通过父模型访问hasMany关联时触发,不会影响你单独查询Post的业务逻辑,无额外副作用。
不推荐的冗余实现
以下两种方案虽然也能达到类似效果,但都存在不必要的性能损耗或冗余代码,不建议使用:
- 手动遍历集合调用
setRelation:$thread->posts->each->setRelation('thread', $thread),属于重复实现框架已内置的逻辑 - 在hasMany关联上额外加预加载
->with('thread'):会额外生成一条查询关联Thread的SQL,而你本身已经持有当前Thread实例,属于完全冗余的查询。
内容的提问来源于stack exchange,提问作者Stalinko
相关产品推荐
相关产品推荐

