¿Cómo funciona un service container?

Clase 24 de 33Curso Avanzado de Laravel

En la clase pasada vimos como es el ciclo de vida de una petición, ahora vamos a conocer acerca del Contenedor de Servicios de Laravel o, como se suele llamar, el Service Container.

El Service Container es una herramienta poderosa para administrar las dependencias de clases, nos permite realizar inyección de dependencias. Cuando hablamos de inyección de dependencias significa que las dependencias de clase se "inyectan" en la clase a través del constructor o, en algunos casos, métodos "setter".

Si quieres saber más en detalle acerca de la inyección de dependencias, podemos leer el artículo del creador del Framework Symfony, Fabien Potencier:v http://fabien.potencier.org/what-is-dependency-injection.html.

Hay muchas maneras de acceder a la instancia del container, en Laravel es tan simple como usar el helper app().

$container = app();

Cómo funcionan los Service Containers

Una de sus funciones es poder inyectar una dependencia dentro de una clase por medio del constructor, por ejemplo:

De manera que, en lugar de tener que hacer un new AnotherClass, simplemente lo colocamos como parámetro del constructor. El contenedor va saber cómo instanciar las dependencias de tal manera que, suponiendo que AnotherClass no tiene dependencias propias, sería algo como:

$instance = new MyClass(new AnotherClass());

Si tuviera dependencias propias, el container también la va a resolver de manera recursiva hasta que no haya más.

Una comprensión profunda del Service Container de Laravel es esencial para construir una aplicación potente y grande, así como para contribuir al core de Laravel.

Cómo usamos los servicios dentro del container de una aplicación

Acá es donde aparece la palabra binding, uno de esos términos que se aplica en muchos lugares, pero que en Laravel nos ayuda a vincular un servicio a la Aplicación. Al hacer esto, podemos vincular implementaciones de nuestras dependencias o servicios y poder acceder a ellas dentro del Container. Casi todos los bindings del contenedor de servicios se registran en los Services Providers.

Y, por otro lado, no es necesario vincular clases en el Container si no dependen de ninguna interfaz, ya que se resuelven mediante reflexión. Pero si necesitamos levantar servicios específicos o que dependen de una interfaz, dentro de la documentación de Laravel vamos a encontrar como hacer los distintos tipos de Bindings: https://laravel.com/docs/7.x/container#binding.

Por ejemplo, dentro de un Service Provider:

$this->app->bind( 'App\Contracts\PaymentGateway', 'App\Services\MercadoPagoGateway' );

Esta declaración le dice al Container que debe inyectar el MercadoPagoGateway cuando una clase necesita una implementación de PaymentGateway. Ahora podemos utilizar en cualquier parte de nuestra aplicación la interfaz PaymentGateway.

public function __construct(PaymentGateway $payments) { $this->payments = $payments; }

En la siguiente clase hablaremos un poco de los Services Providers. :muscle: