Introducción

Los proveedores de servicios son la parte central del inicio básico de una aplicación Laravel (bootstrapping). Tu propia aplicación, así como todos los servicios principales de Laravel son iniciados rápidamente usando proveedores de servicios.

Pero, ¿qué queremos decir por «inicio básico (bootstrapped)»? En general, nos referimos a registrar cosas, incluyendo registrar enlaces de contenedores de servicios, listeners de eventos, middleware e incluso rutas. Los proveedores de servicios son el lugar principal para configurar tu aplicación.

Si abres el archivo config/app.php incluido con Laravel, verás un arreglo providers. Estas son todas las clases de proveedores de servicios que serán cargados por tu aplicación. Observa que muchos de éstos son proveedores «diferidos», lo que significa que no serán cargados en cada solicitud, sino sólo cuando los servicios que proporcionan sean necesarios.

En este resumen aprenderás a escribir tus propios proveedores de servicio y registrarlos en tu aplicación de Laravel.

Escribiendo proveedores de servicios

Todos los proveedores de servicios extienden de la clase Illuminate\Support\ServiceProvider. La mayoría de los proveedores de servicio contienen un método register y boot. Dentro del método register, debes enlazar cosas sólo al contenedor de servicios. Nunca debes tratar de registrar ningún listener de eventos, rutas o cualquier otra pieza de funcionalidad dentro del método register.

La línea de comandos Artisan puede generar un nuevo proveedor mediante el comando make:provider:

php artisan make:provider RiakServiceProvider

Método register

Como mencionamos anteriormente, dentro del método register, debes sólo enlazar cosas al contenedor de servicio. Nunca debes intentar registrar ningún listener de eventos, rutas o cualquier otra pieza de funcionalidad dentro del método register. De lo contrario, puedes accidentalmente usar un servicio que es proporcionado por un proveedor de servicio que no aún no se ha cargado.

Vamos a dar un vistazo a un proveedor de servicio básico. Dentro de cualquiera de los métodos de tu proveedor de servicios, siempre tienes acceso a la propiedad $app que proporciona acceso al contenedor de servicios:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Riak\Connection;

class RiakServiceProvider extends ServiceProvider
{
    /**
    * Register any application services.
    *
    * @return void
    */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }
}

Este proveedor de servicios sólo define un método register y usa dicho método para definir una implementación de Riak\Connection en el contenedor de servicios. Si no entiendes cómo el contenedor de servicios funciona, revisa su documentación.

Propiedades bindings y singletons

Si tu proveedor de servicios registra muchos bindings simples, puedes querer usar las propiedades bindings y singletons en lugar de manualmente registrar cada binding de contenedor. Cuando el proveedor de servicios es cargado por el framework, automáticamente comprobará dichas propiedades y registrará sus bindings:

<?php

namespace App\Providers;

use App\Contracts\DowntimeNotifier;
use App\Contracts\ServerProvider;
use App\Services\DigitalOceanServerProvider;
use App\Services\PingdomDowntimeNotifier;
use App\Services\ServerToolsProvider;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
    * All of the container bindings that should be registered.
    *
    * @var array
    */
    public $bindings = [
        ServerProvider::class => DigitalOceanServerProvider::class,
    ];

    /**
    * All of the container singletons that should be registered.
    *
    * @var array
    */
    public $singletons = [
        DowntimeNotifier::class => PingdomDowntimeNotifier::class,
        ServerToolsProvider::class => ServerToolsProvider::class,
    ];
}

Método boot

Entonces, ¿qué sucede si necesitamos registrar un view composer dentro de nuestro proveedor de servicios? Esto debería ser hecho dentro del método boot. Este método es llamado luego de que todos los demás proveedores de servicio sean registrados, lo que quiere decir que tienes acceso a todos los demás servicios que han sido registrados por el framework:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
    * Bootstrap any application services.
    *
    * @return void
    */
    public function boot()
    {
        view()->composer('view', function () {
            //
        });
    }
}

Inyección de dependencias en el método boot

Puedes declarar dependencias para el método boot de tu proveedor de servicios. El contenedor de servicios inyectará automáticamente cualquier dependencia que necesites:

use Illuminate\Contracts\Routing\ResponseFactory;

public function boot(ResponseFactory $response)
{
    $response->macro('caps', function ($value) {
        //
    });
}

Registrando proveedores

Todos los proveedores de servicios son registrados en el archivo de configuración config/app.php. Este archivo contiene un arreglo providers donde puedes listar los nombres de clase de tus proveedores de servicios. Por defecto, una serie de proveedores de servicios del núcleo de Laravel son listados en este arreglo. Estos proveedores hacen el inicio básico (bootstrap) de los componentes de Laravel del núcleo, como mailer, queue, cache, entre otros.

Para registrar tu proveedor, agrégalo al arreglo:

'providers' => [
    // Other Service Providers

    App\Providers\ComposerServiceProvider::class,
],

Proveedores diferidos

Si tu proveedor sólo está registrando enlaces en el contenedor de servicios, puedes elegir diferir su registro hasta que uno de los enlaces registrados sea necesitado realmente. Diferir la carga de dicho proveedor mejorará el rendimiento de tu aplicación, ya que éste no es cargado desde el sistema de archivos en cada solicitud.

Laravel compila y almacena una lista de todos los servicios suministrados por proveedores de servicios diferidos, junto con el nombre de clase de su proveedor de servicio. Luego, sólo cuando intentas resolver uno de estos servicios Laravel carga el proveedor de servicio.

Para diferir la carga de un proveedor, implementa la interfaz \Illuminate\Contracts\Support\DeferrableProvider y define un método provides. El método provides debe retornar los enlaces del contenedor de servicio registrados por el proveedor:

<?php

namespace App\Providers;

use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use Riak\Connection;

class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
    * Register any application services.
    *
    * @return void
    */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection($app['config']['riak']);
        });
    }

    /**
    * Get the services provided by the provider.
    *
    * @return array
    */
    public function provides()
    {
        return [Connection::class];
    }
}

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Contenedor de servicios - Documentación de Laravel 6 Lección siguiente Facades - Documentación de Laravel 6