跳转到主要内容

什么是关联

数据库中的表之间经常存在关联。例如一篇博客文章有多条评论,一笔订单归属于下单的用户。 Eloquent 提供了简洁定义和操作这些关联的方式。关联作为 Eloquent 模型的方法进行定义。
本页以 UserPostCommentTag 等模型为例。假设这些模型与表已经创建好了。
Eloquent 支持的主要关联类型:

hasOne(一对一)

hasOne 表示某模型拥有另一个模型的一条记录。例如 User 拥有一个 Profile

定义关联

User 模型定义 profile 方法:
Eloquent 根据父模型名推断外键,此处会假定 profiles 表有 user_id 列。

获取关联数据

关联可以作为属性访问:
以属性方式调用关联方法时,Eloquent 会自动发起查询并返回数据。这称为「动态关联属性」。

belongsTo(一对一的反向)

belongsTohasOne 的反向,定义在拥有外键的一侧。例如 Profile 属于 User

定义关联

Eloquent 会用「方法名 + _id」(此处为 user_id)作为外键。

获取关联数据

hasMany(一对多)

hasMany 是最常见的一对多关联。例如一篇 Post 拥有多条 Comment

定义关联

Eloquent 会假定 comments 表有 post_id

获取关联数据

hasMany 返回集合:
也可以追加查询条件:

反向关联(belongsTo)

从评论访问文章:

belongsToMany(多对多)

多对多用于两个模型互相拥有多个关联。例如 Post 有多个 TagTag 也属于多个 Post

表结构

多对多需要中间表。例如 PostTag 使用 post_tag 中间表:
Eloquent 会按字母顺序拼接两个模型名推断中间表名(post + tagpost_tag)。

定义关联

Tag 上同样定义即可反向访问:

获取关联数据

增删关联数据

attach 添加、detach 删除中间表记录:
sync 会自动删除未指定的中间表记录,只保留传入的 ID。

预加载(Eager Loading)

什么是 N+1 问题

以属性方式访问关联,Eloquent 每次都会发查询。这称为「延迟加载」。在循环中访问会产生 N+1 问题。
100 篇文章会产生共 101 次查询,性能问题很大。

with() 预加载

with() 一次性把关联取回来:
执行的 SQL 只有两条:

同时预加载多个关联

嵌套预加载

用点号访问嵌套关联:
预加载对避免 N+1 至关重要。循环中访问关联时请养成使用 with() 的习惯。

下一步

Eloquent 入门

回顾 Eloquent 的基本 CRUD。
最后修改于 2026年7月18日