Comprender la inyección de dependencia contenedor en PHP

Un contenedor de inyección de dependencia es un objeto que sabe cómo conectar automáticamente las clases.
El término de conexión automática implica crear instancias y configurar objetos correctamente. Esta no es una tarea fácil, por eso hay varias bibliotecas que abordan esta funcionalidad.


El componente DependencyInjection proporcionado por el marco de Symfony es un contenedor de inyección de dependencia ordenado que Composer puede instalar fácilmente.
En el futuro, avancemos y creemos un directorio di-container donde ejecutaremos estos comandos y configuraremos nuestro proyecto:

composer require symfony/dependency-injection

El resultado sugiere que deberíamos instalar algunos paquetes adicionales:

Necesitamos asegurarnos de agregar los paquetes symfony/yaml y symfony/config ejecutando los siguientes comandos de consola:

composer require symfony/yaml
composer require symfony/config

El paquete symfony/yaml instala el componente Symfony Yaml. Este componente analiza las cadenas YAML en matrices PHP y viceversa. El paquete symfony/config instala el componente Symfony Config. Este componente proporciona clases para ayudarnos a encontrar, cargar, combinar, autocompletar y validar valores de configuración de fuentes, como archivos YAML, XML, INI o incluso una base de datos.
Los paquetes symfony/dependency-injection, symfony/yaml y symfony/config son un buen ejemplo de componentes acoplados libremente. Mientras que los tres trabajan de la mano para ofrecer el alcance completo de la funcionalidad de inyección de dependencia, los componentes siguen los principios del acoplamiento suelto.

Echa un vistazo a http://symfony.com/doc/current/components/dependency_injection.html para obtener más información sobre el componente de inyección de dependencia de Symfony.

Ahora sigamos y creemos el archivo de configuración container.yml dentro del directorio dicontainer:

services:
config:
class: Config
logger:
class: Logger
app:
class: App
autowire: true

El archivo container.yml tiene una estructura específica que comienza con los servicios de palabras clave.
Sin profundizar en ello, basta con decir que el contenedor del servicio es el nombre de Symfony para el contenedor de inyección de dependencia, mientras que el servicio es cualquier objeto PHP que realiza alguna tarea, básicamente, una instancia de una clase de cualquier tipo.
Justo debajo de la etiqueta de servicios, tenemos las etiquetas de configuración, registrador y aplicación. Estos denotan una declaración de tres servicios distintivos. Podríamos haberlos nombrado fácilmente the_config, the_logger, the_app o cualquier otra cosa que prefieramos. Al profundizar en los servicios individuales, vemos que la etiqueta de clase es común a los tres servicios. La etiqueta de clase le dice al contenedor qué clase instanciar cuando se solicita una instancia de servicio determinada. Finalmente, la característica de autoconexión utilizada dentro de la definición del servicio de aplicación permite que el subsistema de autoconexión detecte las dependencias de la clase de aplicación analizando su constructor. Esto hace que sea muy simple para un código de cliente obtener una instancia de la clase de aplicación sin siquiera tener en cuenta los requisitos de $config y $logger en la clase de aplicación __construct().

Con el archivo container.yml en su lugar, sigamos adelante y creemos el archivo index.php dentro del directorio di-container:

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
interface ConfigInterface { /* … /} interface LoggerInterface { //} class Config implements ConfigInterface { //} class Logger implements LoggerInterface { //} class App { / … */}
// Bootstrapping
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__));
$loader->load('container.yml');
$container->compile();
// Client code
$app = $container->get('app');
$app->run();

Asegúrese de reemplazar todo, desde ConfigInterface a la aplicación con código exacto que teníamos en nuestro tercer ejemplo desde la sección Comprensión de la inyección de dependencias.

Comenzamos incluyendo el archivo autoload.php para que funcione la carga automática de nuestro componente contenedor de dependencia. El código que sigue a las declaraciones de uso es el mismo código que teníamos en la sección Comprensión de la inyección de dependencia. La parte interesante viene después de eso. La instancia de ContainerBuilder se crea y se pasa a YamlFileLoader, que carga el archivo container.yml. Justo después de cargar el archivo, llamamos al método compile() en la instancia de $container. La ejecución de compile() permite que el contenedor recoja la etiqueta de servicio de cableado automático, entre otras cosas. Finalmente estamos
usando el método get() en la instancia de $container para obtener una instancia del servicio de la aplicación. El cliente, en este caso, no tiene conocimiento inicial de los argumentos que se pasan a la instancia de la aplicación; el contenedor de dependencias lo manejó todo por sí mismo basado en una configuración container.yml.
Usando sugerencias de tipo de interfaz y el contenedor, podemos escribir código más reutilizable, comprobable y desacoplado.

Echa un vistazo a http://symfony.com/doc/current/service_container.html para obtener más información sobre el contenedor del servicio de Symfony.

Comparte