Service Providers en Laravel 11: principales aspectos que debes saber
- Publicado el 06 septiembre, 2024
- Palabras: 1332
Los service providers han sido la funcionalidad principal de Laravel desde el principio. Sin embargo, en Laravel 11, la lista de service providers cambió y solo quedó AppServiceProvider. Entonces, ¿qué necesitan saber los desarrolladores ahora?
#Un poco de teoria: Objetivo principal de los services providers
El objetivo principal de los service providers es ser el lugar central para registrar clases o diversas configuraciones globales.
En mi opinión, debería haberse llamado “Class Configuration” (Configuración de clase) o algo similar, no service providers (Proveedor de servicios), para evitar confusiones. Pero tenemos que trabajar con lo que tenemos, ¿no?
En AppServiceProvider, normalmente se registran singletons, event listeners y configuraciones adicionales opcionales para diversas características de Laravel, como recursos de API, relaciones polimórficas, etc.
#AppServiceProvider, el service provicer por defecto “En blanco”
Después de instalar Laravel 11 el AppServiceProvicer tiene esta pinta
app/Providers/AppServiceProvider.php:
namespace AppProviders;
use IlluminateSupportServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
}
¿Para que son los métodos register() y boot()?
La explicación breve es que el método register() para todos los providers es llamado antes que el método boot().
- register(): aquí, puede agregar los bindings y singletons.
- boot(): aquí es donde puede realizar tareas que pueden depender de otros providers registrados. Puede agregar macros, event listeners, crear gates, etc.
Ahora, veamos los ejemplos de uso para ambos métodos.
#Ejemplos de casos de uso: método register()
Puede registrar un singleton en el service provider, garantizando que solo exista una instancia en toda su aplicación.
Ejemplo 1. Filamento: Registrar página de inicio de sesión personalizada
Aquí sobrescribimos la respuesta usando Singleton con una clase de respuesta personalizada.
public function register(): void
{
$this->app->singleton(
FilamentHttpResponsesAuthContractsLoginResponse::class,
AppHttpResponsesLoginResponse::class
);
}
Aviso: ¿No sabes mucho sobre Singleton? Lo puedes ver en esta interesante web de Patrones de diseño
Ejemplo 2. Telescope: regístrelo solo localmente
Aquí hay otro ejemplo del paquete Laravel Telescope si desea utilizar el Telescope solo en un entorno local.
public function register(): void
{
if ($this->app->environment('local')) {
$this->app->register(LaravelTelescopeTelescopeServiceProvider::class);
$this->app->register(TelescopeServiceProvider::class);
}
}
Ejemplo 3. Mongo: Registrar un controlador de caché
Otro ejemplo es registrar un controlador de caché.
use AppExtensionsMongoStore;
use IlluminateContractsFoundationApplication;
use IlluminateSupportFacadesCache;
public function register(): void
{
$this->app->booting(function () {
Cache::extend('mongo', function (Application $app) {
return Cache::repository(new MongoStore);
});
});
}
#Ejemplos de casos de uso: método boot()
A continuación, después de ejecutar el método register(), Laravel procesa el método boot() para todos los providers.
A continuación, se muestran algunos ejemplos de lo que podemos hacer aquí:
Ejemplo 1. Evitar el Lazy loading (carga diferida)
use IlluminateDatabaseEloquentModel;
public function boot(): void
{
Model::preventLazyLoading(! $this->app->isProduction());
}
Ejemplo 2. Definir permisos: Gates
La definición de los Gates normalmente también se añade en el AppServiceProvider.
use AppModelsPost;
use AppModelsUser;
use IlluminateSupportFacadesGate;
public function boot(): void
{
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
}
Ejemplo 3. Recurso API: Eliminar "data"
Al trabajar con API, puede eliminar el wrapping (envoltorio) de respuesta con la clave ‘data’.
use IlluminateHttpResourcesJsonJsonResource;
public function boot(): void
{
JsonResource::withoutWrapping();
}
Ejemplo 4. Registrar componentes de Blade personalizados
Registro manual de componentes Blade.
use IlluminateSupportFacadesBlade;
public function boot(): void
{
Blade::component('package-alert', Alert::class);
}
Ejemplo 5. Componente Blade: Personalizar el Namespace
O bien, cargar automáticamente clases de componentes por convención.
use IlluminateSupportFacadesBlade;
public function boot(): void
{
Blade::componentNamespace('Nightshade\Views\Components', 'nightshade');
}
Ejemplo 6. Relación polimórfica: MorphMap
El último ejemplo es forzar el uso de un nombre distinto de un nombre de clase totalmente calificado al almacenar un "tipo" para la relación polimórfica.
use IlluminateDatabaseEloquentRelationsRelation;
public function boot(): void
{
Relation::enforceMorphMap([
'post' => 'AppModelsPost',
'video' => 'AppModelsVideo',
]);
}
Estos son solo algunos casos de uso. Para ver más ejemplos, haz clic aquí para ver cuántas veces se menciona "AppServiceProvider" en la documentación oficial de Laravel.
Service Provicers "obsoletos": Laravel 11 vs versiones anteriores
Antes de Laravel 11, había cinco service providers en la instalación predeterminada en la carpeta app/Providers:
- AppServiceProvider.php
- AuthServiceProvider.php
- BroadcastServiceProvider.php
- EventServiceProvider.php
- RouteServiceProvider.php
Cada service provider era responsable de su propia configuración. Por ejemplo, RouteServiceProvider tenía todo lo relacionado con las rutas, y EventServiceProvider tenía eventos, oyentes y observadores de Eloquent.
Desde Laravel 11, los service providers han sido reducidos. Ahora todo está "integrado" en el framework y se puede cambiar en un solo archivo, bootstrap/app.php.
Ejemplo: en el RouteServiceProvider anterior teníamos el generador de límites de velocidad y el suministro de rutas. Además, una constante HOME con un enlace a alguna página.
class RouteServiceProvider extends ServiceProvider
{
public const HOME = '/home';
public function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
}
En Laravel 11, esto ha sido eliminado:
- No hay constante HOME: en su lugar, se debe usar el nombre de la ruta
- Las rutas se configuran en el archivo bootstrap/app.php como parámetros en el método withRouting()
- Además, de manera predeterminada, no hay rutas API: debe instalarlas con php artisan install:api
bootstrap/app.php:
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
Con esta simplificación, ya no es necesario RouteServiceProvider.
Por lo tanto, en Laravel 11, normalmente solo usarás AppServiceProvider sin ningún otro proveedor de servicios más.
#Aún puedes crear proveedores de servicios personalizados
Incluso si obtiene solo un proveedor de servicios de forma predeterminada, puede crear tantos como necesite. Si deseas separar la lógica de diferentes providers, puedes hacerlo.
Digamos que necesita algunas macros de vista, recursos compartidos, etc. Con un comando artisan, puedes crear un ViewServiceProvider.
php artisan make:provider ViewServiceProvider
En ViewServiceProvider, agrega toda la lógica que necesites.
Recuerda registrar todos tus proveedores de servicios en el archivo bootstrap/providers.php.
bootstrap/providers.php:
return [
AppProvidersAppServiceProvider::class,
AppProvidersViewServiceProvider::class, // nuevo service provider
];
Un buen ejemplo de cómo utilizar varios service proficers es el uso que hace Filament de ellos. Cada servide provider es para un panel independiente con su conjunto de configuraciones globales; consulte la documentación de Filament.
#Service Providers para paquetes
Un tema aparte para los servide proficers es la creación de paquetes de Laravel. En ese caso, es imprescindible contar con un proveedor de servicios porque es una conexión entre el paquete y Laravel.
En el servide provider, proporcionas el archivo de configuración del paquete, migraciones, rutas, archivos de idioma, etc.
Laravel puede cargar automáticamente el proveedor de servicios de paquetes si está definido en composer.json.
"extra": {
"laravel": {
"providers": [
"Barryvdh\Debugbar\ServiceProvider"
]
}
},
Antonio Jenaro
Web Developer
Fuente: Laravel Daily
Inicia la conversación
Hazte miembro de Antonio Jenaro para comenzar a comentar.
Regístrate ahora¿Ya estás registrado? Inicia sesión