¿Qué es la inyección de dependencia en PHP y cómo usarla?
Una metodología popular y bien conocida de desarrollo de software se llama inyección de dependencia, que ayuda a facilitar el flujo asegurando que su software siempre tenga acceso a las herramientas que necesita. Muchos intentan hacer que esta metodología suene bastante compleja, pero en realidad no lo es.
Analicemos qué es la inyección de dependencia, cómo funciona y cómo beneficiará a su software.
¿Qué es la inyección de dependencia?
Una gran analogía para la inyección de dependencia es un trabajador con un conjunto de herramientas que viaja junto con el software mientras se procesa, asegurando que todo fluya sin problemas. El kit de herramientas puede contener todo tipo de cosas, incluidas variables, matrices, objetos , cierres y cualquier otra cosa necesaria para completar la tarea en cuestión.
Cuando el trabajador comienza una nueva tarea (es decir, clase o método), verá los requisitos necesarios y, sin pensarlo, sacará las diferentes herramientas necesarias para completar el trabajo. Esta es la inyección de dependencia en pocas palabras.
Puede llenar su kit de herramientas con lo que necesite, luego, dentro de las clases y métodos del software, especifique las herramientas que necesita, y automáticamente estarán allí para usted.
Instalar Apex Container
Hay muchas implementaciones diferentes, pero todas funcionan básicamente de la misma manera, y usaremos Apex Container ya que es simple y directo. Se supone que ya tiene PHP instalado, y puede verificar si Composer está instalado o no con el comando:
composer --version
Si recibe un error de "comando no encontrado", puede instalar Composer con el siguiente comando:
sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
Ahora cree un directorio en blanco y dentro del directorio ejecute los siguientes comandos:
composer require apex/container
composer require twig/twig
Esto descargará tanto el Apex Container como el popular motor de plantillas Twig, que se utilizará en los ejemplos siguientes. Ambos se pueden encontrar en el subdirectorio / vendor /.
Inyecta tus herramientas
Creemos una clase rápida llamada Car con el siguiente código:
<?php
use TwigLoaderArrayLoader;
class Car
{
public function __construct(
public string $model,
public string $color,
public ArrayLoader $db
) {
echo "I'm a $color $model and have a " . $db::class . "
";
}
}
Esta es una clase simple con dos propiedades, la marca y el color de un automóvil, y carga la clase 'ArrayLoader' de Twig. Guárdelo como car.php y prepárese para poner en práctica la magia de la inyección de dependencia. Abra otro archivo en blanco y agregue el siguiente código:
<?php
use ApexContainerContainer;
// Load Composer packages, and the car.php file
require_once(__DIR__ . '/vendor/autoload.php');
require_once(__DIR__ . '/car.php');
// Create container, and add a couple tools
$cntr = new Container(use_attributes: true);
$cntr->set('model', 'Jaguar');
$cntr->set('color', 'silver');
// Create our car object
$car = $cntr->make('Car');
$car2 = $cntr->make('car', ['color' => 'red']);
Guarde y ejecute este código en la terminal, y los resultados serán:
I'm a silver Jaguar and have a TwigLoaderArrayLoader
I'm a red Jaguar and have a TwigLoaderArrayLoader
En el código anterior, creó una instancia del contenedor (es decir, el kit de herramientas) y agregó un par de herramientas, el color y la marca de un automóvil. En lugar de crear el objeto auto con el nuevo Car normal (); , se creó mediante el método make () del contenedor. Esto pasó por la clase primero para verificar los requisitos, luego miró qué elementos (es decir, herramientas) teníamos disponibles y los inyectó en la clase antes de devolverlos.
Notará la declaración de uso en la parte superior del archivo para ArrayLoader, y el tercer argumento en el constructor también solicita un ArrayLoader . Cuando el contenedor miró los requisitos de la clase, notó ambos aspectos, creó automáticamente una instancia de ArrayLoader `y la inyectó en el constructor. Esto se llama cableado automático.
Ampliación con inyección de atributos
Yendo un paso más allá, en lugar de solo inyectar en el constructor, también podemos inyectar directamente en las propiedades a través de atributos. Modifique el archivo del automóvil y cámbielo a:
<?php
use TwigLoaderArrayLoader;
use ApexContainerContainer;
class Car
{
#[Inject(Container::class)]
public Container $cntr;
public function __construct(
public string $model,
public string $color,
public ArrayLoader $db
) {
echo "I'm a $color $model and have a " . $db::class . "
";
}
function getCost()
{
echo "Class is " . $this->cntr::class . "
";
}
}
Las únicas modificaciones se le añadió una nueva declaración de uso, se añadió la propiedad con el atributo de la clase de contenedor, y hemos añadido un nuevo getCost () la función . En la parte inferior del código de prueba que ejecutó anteriormente, agregue la línea:
$car->getCost();
Ahora ejecute el código nuevamente y los resultados serán:
I'm a silver Jaguar and have a TwigLoaderArrayLoader
I'm a red Jaguar and have a TwigLoaderArrayLoader
Class is ApexContainerContainer
Esta vez, cuando se cargó la clase car.php , el contenedor también miró sus propiedades, notó el atributo Inject que llamaba a la clase contenedora e inyectó una instancia de la misma. A veces se prefiere inyectar mediante atributos de esta manera, ya que ayuda a mantener las cosas más limpias y legibles.
Obtenga sus propias herramientas
En lugar de inyectar siempre elementos, ¿qué sucede si desea recuperar un elemento del contenedor usted mismo? Esto se puede hacer fácilmente con el método get () del contenedor. Dentro del archivo car.php , modifique la función getCost () agregada anteriormente con:
function getCost()
{
$price = $this->cntr->get('car_price');
echo "The price is $price
";
}
Ahora, dentro del código de prueba que ha estado ejecutando, en cualquier lugar antes de la línea que llama a getCost () agregue una línea como:
$cntr->set('car_price', 24995);
Ahora ejecute el código y los resultados serán:
I'm a silver Jaguar and have a TwigLoaderArrayLoader
I'm a red Jaguar and have a TwigLoaderArrayLoader
Price is 24999
No es necesario que inyecte sus elementos y siempre puede obtener fácilmente lo que necesita con el método get () como se muestra arriba.
Avanzar con la inyección de dependencia
Ahora tiene una buena descripción general de qué es exactamente la inyección de dependencia y cómo funciona. Nuevamente, lo anterior es solo una de muchas implementaciones, pero todas las implementaciones que existen funcionan de la misma manera con los métodos get () / set () / make () .
Sin embargo, aún hay más en la inyección de dependencias, como el archivo de definiciones y la inyección de métodos. Si está interesado, consulte el manual de Apex Container u otras implementaciones.