概述
Eloquent 模型在每次实例化时都会执行两个阶段:「启动处理(boot)」和「初始化处理(initialize)」。只要在 trait 中定义符合规约的方法,模型use 该 trait 时就会自动调用它们。
利用这一机制,可以干净地实现向模型注入功能的 trait。Laravel 框架自身也在 SoftDeletes、HasUuids、HasUlids 等大量 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 向模型注入功能。这是包开发中向模型追加功能的经典模式。