Esta página da por sabido el contenido de Fundamentos del desarrollo de paquetes. Es recomendable entender primero cómo funciona un service provider normal.
Por qué necesitas providers diferidos
Un service provider normal ejecutaregister() y boot() en cada petición. Es un desperdicio inicializar en todas las páginas funcionalidades como el envío de correos, colas o caché si no se usan en muchas de ellas.
Interfaz DeferrableProvider
Illuminate\Contracts\Support\DeferrableProvider es una interfaz muy simple con un único método provides().
Implementación básica
La implementación de un provider diferido consta de tres pasos.1
Implementar DeferrableProvider
2
Enlazar los servicios en register()
Igual que en un provider normal, define los bindings en
register().3
Devolver los servicios registrados en provides()
provides() debe devolver todos los servicios que has enlazado en register(). Laravel usa esta lista para saber al pedir qué servicio debe cargar este provider.Cómo funciona el manifest de servicios
En el arranque, Laravel genera un archivo llamadobootstrap/cache/services.php. Este manifest contiene la lista de servicios que ofrecen los providers diferidos.
Flujo interno de funcionamiento
Importancia del método provides()
Si enprovides() te olvidas de algún servicio, ese servicio no se resolverá nunca.
$bindings / $singletons.
Limitaciones de los providers diferidos
Los providers diferidos son adecuados solo para providers cuyo único cometido es registrar bindings en el contenedor. Los providers que hacen lo siguiente enboot() no pueden ser diferidos.
Método when() — registro por evento
Con el métodowhen() puedes hacer que un provider se registre cuando se dispare un evento concreto. Es útil para providers que solo se necesitan en contextos específicos, como procesos de jobs.
when(), el provider se cargará aunque no se haya resuelto directamente ningún servicio.
Uso en el desarrollo de paquetes
Al distribuir un paquete de terceros, los providers diferidos también contribuyen al rendimiento de las aplicaciones de tus usuarios.Patrón recomendado
mergeConfigFrom() comprueba internamente si la configuración ya está cacheada, así que es seguro llamarlo dentro del register() de un provider diferido. Eso sí, si la configuración está cacheada, no hará nada.Separar el registro de comandos Artisan con runningInConsole()
Como el registro de comandos solo es necesario al arrancar Artisan, protégelo con runningInConsole(). Si además quieres diferir el provider que registra los comandos, incluye las clases de comando en provides() o proporciona un provider separado dedicado a los comandos.
Ejemplos en el core de Laravel
Muchos de los providers del core de Laravel son diferidos. Es un diseño pensado para no cargar de forma inmediata todos los servicios que no se usan en cada petición.
En una aplicación con solo endpoints de API puede darse el caso de que
MailServiceProvider o BroadcastServiceProvider no se carguen nunca durante una petición.
Criterios para decidir si diferir
Servicios adecuados para diferir
Servicios adecuados para diferir
- Servicios que no se usan en todas las peticiones (correo, reports, clientes de APIs externas, etc.)
- Servicios cuya inicialización requiere conexiones externas o lectura de archivos.
- Servicios con grafos de objetos pesados.
- Providers que solo aportan comandos usados por CLI.
Servicios no adecuados para diferir
Servicios no adecuados para diferir
- Providers que registran rutas (
loadRoutesFrom, etc.). - Providers que registran middlewares o handlers de excepciones activos permanentemente.
- Providers que registran global scopes u observers de Eloquent.
- Servicios ligeros usados en la mayoría de peticiones (donde la sobrecarga del diferido puede ser mayor).
Páginas relacionadas
Fundamentos del desarrollo de paquetes
Aprende cómo desarrollar paquetes Laravel centrados en los service providers.
Gestión de la compatibilidad de versiones de paquetes
Estrategias de mantenimiento de paquetes ante grandes actualizaciones de versión de Laravel y PHP.