跳转到主要内容

概述

Eloquent 模型在每次实例化时都会执行两个阶段:「启动处理(boot)」和「初始化处理(initialize)」。只要在 trait 中定义符合规约的方法,模型 use 该 trait 时就会自动调用它们。 利用这一机制,可以干净地实现向模型注入功能的 trait。Laravel 框架自身也在 SoftDeletesHasUuidsHasUlids 等大量 trait 中广泛运用此模式。

boot 与 initialize 的区别


命名规约

bootXxx()

在 trait 名称前加上 boot 前缀,定义 static 方法,即可在模型启动时被调用一次。
在模型中使用:

initializeXxx()

在 trait 名称前加上 initialize 前缀,定义实例方法,即可在每次 new 模型时被调用。
也可以用于动态添加 $casts

通过 PHP Attribute 显式指定

从 Laravel 12 起,可以不依赖命名规约,通过 PHP Attribute 显式标注方法。
使用 PHP Attribute 后,方法名不再受 trait 名称的约束,可以取更有语义的名字。也可以在同一个 trait 中定义多个 #[Boot]#[Initialize] 方法。

实用示例:包开发中的应用

自动添加全局作用域

添加默认 cast

通过 Eloquent 事件自动处理


Laravel 框架内的示例

Laravel 框架本身在众多 trait 中都采用了这一模式。 阅读这些参考实现,有助于加深对该模式的理解。

注意事项

清除模型缓存

由于 boot* 每个类只执行一次,在测试环境中需要特别注意。可以通过 Model::clearBootedModels() 重置已启动的缓存。

执行顺序

当同一模型 use 多个 trait 时,bootXxx() / initializeXxx() 会按 PHP 的 trait 解析顺序(即声明顺序)被调用。若 trait 之间存在依赖关系,请注意 use 的顺序。

总结

在 trait 中实现 bootXxx() / initializeXxx(),就能通过一行 use 向模型注入功能。这是包开发中向模型追加功能的经典模式。
最后修改于 2026年7月18日