Resumen
Cada vez que se instancia un modelo Eloquent se ejecutan dos fases: el “arranque” (boot) y la “inicialización” (initialize). Si defines determinados métodos en un trait, basta con que el modelo lo declare medianteuse para que Eloquent los descubra y los invoque automáticamente.
Gracias a este mecanismo puedes implementar traits que inyectan funcionalidad en tus modelos de forma limpia. El propio framework Laravel aprovecha este patrón en muchos traits como SoftDeletes, HasUuids o HasUlids.
Diferencia entre boot e initialize
Convenciones de nomenclatura
bootXxx()
Si defines un métodostatic con el prefijo boot seguido del nombre del trait, se invocará una sola vez al arrancar el modelo.
initializeXxx()
Si defines un método de instancia con el prefijoinitialize seguido del nombre del trait, se invocará cada vez que se haga new sobre el modelo.
$casts:
Especificación explícita mediante PHP Attributes
A partir de Laravel 12 puedes indicar los métodos explícitamente con PHP Attributes, sin depender de la convención de nomenclatura.Al usar PHP Attributes, el nombre del método deja de estar atado al nombre del trait, así que puedes elegir nombres realmente significativos. Además, puedes definir varios métodos
#[Boot] o #[Initialize] dentro del mismo trait.Ejemplos prácticos: uso en el desarrollo de paquetes
Añadir un global scope automáticamente
Añadir casts por defecto
Procesamiento automático mediante eventos de Eloquent
Ejemplos dentro del framework Laravel
El propio framework Laravel adopta este patrón en muchos de sus traits.
Leer estas implementaciones como referencia ayuda a entender el patrón con más profundidad.
Consideraciones
Limpiar la caché de modelos
Comoboot* solo se ejecuta una vez por clase, hay que tener cuidado en el entorno de pruebas. Puedes resetear la caché de arranque con Model::clearBootedModels().
Orden de ejecución
Cuando un mismo modelo haceuse de varios traits, los métodos bootXxx() / initializeXxx() se invocan en el orden de resolución de traits de PHP (el orden de declaración). Si existen dependencias entre ellos, ten en cuenta el orden en el use.
Resumen
Implementar
bootXxx() / initializeXxx() en un trait permite inyectar funcionalidad en un modelo con una sola línea use. Es el patrón habitual para añadir funciones a modelos desde un paquete.