Skip to main content

什么是自定义 Pivot 模型

belongsToMany(多对多)的中间表默认会作为原生的 Illuminate\Database\Eloquent\Relations\Pivot 实例来处理。当需要在中间表增加额外列(如审批时间、角色种类),或添加访问器、修改器、自定义方法时,可以创建继承自 Pivot 的自定义模型。
belongsToMany 的定义中调用 using(),告诉关联使用该自定义模型。
保存自定义 Pivot 模型时,模型名请务必按字母顺序的单数形式命名(应写为 RoleUser 而非 UserRole)。这只是一种命名约定,实际类名可以自由选择。

通过 as() 指定想要访问的属性名

默认情况下,中间表的值通过 pivot 属性访问。使用 as() 方法可以修改这个名字。

附加列与时间戳

中间表中若存在如 approved 这样的额外列,需要使用 withPivot() 明确将其纳入取回范围。若要维护 created_at / updated_at,请调用 withTimestamps()
只有当 Pivot 模型通过 using() 明确指定时,Eloquent 才会自动更新中间表的 updated_at。即便直接使用默认的 Pivot 类,withTimestamps() 也能正常工作,但通过 using() 指定自定义模型才能使用自定义事件与自定义类型转换等特性。

从 Pivot 模型反向引用

自定义 Pivot 模型可以自由定义指向声明方模型和关联方模型的 belongsTo 关联。
这样,即便单独取回 Pivot 模型,也能通过 $roleUser->role$roleUser->user 访问关联模型。但若想在执行父查询时自动预加载这些关联,可以使用下面介绍的 chaperone() 方法。

通过 chaperone() 自动预加载(Laravel 13)

Laravel 13 新增了 chaperone() 方法,可以在执行 belongsToMany 查询时,把 Pivot 模型上定义的 role() / user()belongsTo 关联自动完成 hydrate(相当于预加载后的关联绑定)。
调用 chaperone() 后,Eloquent 会自动推测 Pivot 模型(RoleUser)中 belongsTo 关联的名称。像 Role::with('users') 那样取回集合时,会在无需额外查询的情况下为每个 Pivot 挂接声明方模型和关联方模型的引用。

使用非标准关联名称的情况

若 Pivot 模型的 belongsTo 关联方法名称与标准命名(声明方和关联方模型名的驼峰单数形式)不同,可以通过 chaperone() 的参数显式指定。
chaperone() 是一种「消除通过中间表引用时的 N+1 问题」的机制。对于经常从 Pivot 模型访问父模型信息(例如同时展示审批时间和用户名)的应用,与常规的 with() 预加载结合使用会非常有效。

下一步

关联

回顾包含 belongsToMany 在内的基本关联定义方式。

Eloquent Observer 与模型事件

学习使用模型事件来 hook Pivot 模型的保存与更新。
最后修改于 2026年9月11日