Cómo usar inyección de dependencias en PHP

Inyeccion de Dependencias es uno de esos patrones de diseño que tienen un nombre “elegante” y “rimbombante”.

Sin embargo, es un patrón extremadamente sencillo y muchísimos programadores lo utilizan sin darse cuenta que lo están usando. También muchos "expertos" lo complican mucho más de lo necesario.

Existen dos tipos de inyección, el primer tipo es a través del constructor de la clase y la segundo a través de setters. Éste tutorial cubre exclusivamente la inyección de dependencias con constructores.

En palabras simples la inyección de dependencias te permite pasar a través del constructor de la clase todos los objetos que necesita tu clase para funcionar. En palabras aún más simples: Una dependencia es un instancia de la clase B, que la clase A necesita para poder hacer su trabajo.

Por ejemplo, un carro depende de un motor para hacer su trabajo. Un código sin inyección de dependencias lucirīa así:

El problema con la implementación anterior, es que la clase “Motor” se declara implícitamente o dicho de otra forma: No es posible saber que existe dicho objeto hasta inspeccionar código fuente de la clase Carro. Por lo tanto no solamente la declaración es implícita sino que las clases también están acopladas.

Es decir, que no puedes sustituir la clase Motor, por MotorDiesel o MotorBiodiesel sin modificar el código de la clase Carro. De ésta misma manera, la clase se vuelve difícil de mantener y difícil de depurar. Es aquí donde entra en juego la inyección de dependencia, ya que cuando utilizas éste patrón estás haciendo explicita la declaración de la clase y por lo tanto desacoplando Carro de Motor. El código anterior, cambia a:

Y listo! Eso es inyección de dependencias! Nada difícil ¿verdad?

Cuando usas inyección de dependencias, si quieres cambiar el “Motor” del “Carro”, lo único que tienes que hacer es crear una clase que extienda la clase Motor y pasarla como dependencia de la clase carro y listo!

Si encuentras un error en la implementación anterior, o no estás seguro de como utilizar inyección de dependencias en PHP déjame un comentario y te contesto!

Referencias:
http://fabien.potencier.org/article/11/what-is-dependency-injection
http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html
http://martinfowler.com/articles/injection.html
http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/

  • DimcraftLq

    en el constructor no seria correcto?  $this->motor= clone($motor);

  • Yail Anderson

    DimcraftLq para que clonar la clase?

  • DimcraftLq

    no se esta clonando la clase, sino un objeto de dicha clase. Mmmm... creo que lo correcto seria copia el objeto para no modificar el objeto pasado como parametro, recordemos que los objetos tienen distinto comportamiento al de las variables cuando se pasan como parametro en php.

  • DimcraftLq Realmente depende del uso que le estés dando a la inyección de dependencias, el principal objetivo de la inyección es re-utilizar el mismo objeto, por lo que si quieres utilizar "clone" quizá convendría más utilizar una Factory en lugar de la Inyección. 
    Si no piensas re-utilizar el objeto que estás inyectando, desde mi punto de vista no tiene sentido inyectar la dependencia.

  • Pingback: Implementación de Factory en PHP | Alan Chavez()

  • cazaplanetas

    Sigo sin entenderlo, pero gracias por el intento

  • Pablo Tobar

    Hola, como recomendación creo que seria bueno utilizar abstracción en vez de una clase motor y una pregunta: es necesario definir que la variable $motor sea del tipo motor en el constructor de la clase Carro? creería que así es suficiente: public function __construct($motor) {...sobre todo si vas a utilizar repositorios aunque con solo mencionarlo ya pasamos a IOC

  • montalvoMiguel

    Cool bien explicado

  • ricardo espinoza

    Excelente! He estado siguiendo tus post y tus videos ultimamente y debo decirte que he aprendido muchísimo. Gracias, continua con tu excelente trabajo. Saludos.

  • Corovino

    La verdad no entendi yo uso seguido código parecido en el constructor, pero ni entiendo el uso practico

    • Te pido una disculpa porque utilicé un pésimo ejemplo en éste artículo, y lo voy a editar para utilizar un ejemplo real.

      Por el momento, te respondo con el uso práctico de la inyección de dependencias:

      El objetivo de la inyección de dependencias, es exponer las dependencias de una clase. Por ejemplo, supongamos que tienes una clase para tarjetas de crédito y quieres procesar un cobro en otra sección de la página, y escribes:

      $tarjeta = new TarjetaCredito("1234 5678 9012 3456", 5, 2008);
      $t->cobrar(100);

      Y al momento de ejecutar tu código, el cobro falla.

      Entonces te pones a investigar porque el cobró falló, y te das cuenta que al inspeccionar la clase antes de poder procesar un pago; necesitas instanciar el Procesador de Pagos.

      Por lo tanto para poder re-utilizar la clase en otra sección de tu aplicación, necesitas modificar la clase original o duplicar un montón de código para que funcione apropiadamente.

      Ese tipo de situaciones se pueden evitar si utilizas inyección de dependencias para exponer las dependencias de la clase TarjetaCredito y poder re-utilizarla libremente.

      Por ejemplo, la podrías modificar para que funcione de la siguiente manera:

      $procesadorPagos = new ProcesadorPagos("api.authorize.net", $key, $secret);
      $tarjetaCredito = new TarjetaCredito($processadorPagos, "1234 5678 9012 3456", 5, 2018);
      $tarjetaCredito->cobrar(100);

      Y ahora puedes re-utilizar las clases sin duplicar el código en diferentes partes de tu aplicación.

  • Corovino

    Bueno, aun no entiendo mucho pero me surgen ideas, tratare de crear algunos ejemplos aver que tal, de nuevo gracias por responder

  • Walter Nuñez

    Gracias por la guía pero estoy tratando de implementar este concepto en un código y no lo logro agradezco la ayuda:
    https://stackoverflow.com/questions/36291578/php-help-right-way-to-define-classes-and-called-on-diferents-constructor

  • Christian Vivas

    eso se llama polimorfismo y es uno de los pilares de la POO

  • Hola, gracias por la explicación.
    En Laravel la inyección de dependencias se suele usar sobre los métodos de la clase y no en el constructor, verdad? (he visto ejemplos donde los usan en el constructor también, y mi duda aplica para ambos casos).

    Mi pregunta es, ¿quién envía la instancia que se recibe como parámetro en el método?
    Es decir, entendería si yo mismo creo un objeto de una clase y lo envío como parámetro (sea al constructor o un método).
    Pero en Laravel cuando declaro una ruta y le asocio un método, puedo usar parámetros que no declaro/instancio en ningún momento.
    Dado que no hago una llamada a dicho método, asumo que se hace internamente, pero cómo sabe Laravel qué objeto debe inyectar?, por ejemplo, un objeto Request.

    Espero me ayude a resolver esta duda. Gracias !

    • No he trabajado mucho con Laravel, así que no estoy seguro como Laravel inyecta dependencias, pero estoy casi seguro que utiliza un Dependency Injection Container, o alguna variación del mismo concepto.

      Un Dependency Injection Container es un objeto que sabe como instanciar y configurar objetos. Básicamente, cuando llamas un objeto desde el Container, el Container ya tiene toda la información necesaria para instanciar un objeto determinado.

      Aquí te dejo un artículo al respecto:
      http://fabien.potencier.org/do-you-need-a-dependency-injection-container.html

      Y un proyecto llamado Pimple que te sirve para implementar Dependency Injection Containers.
      http://pimple.sensiolabs.org/

  • Carlos Andres

    Para un programa estilo mvc donde hay una carpeta App y una llamada Core como puedo inyectar objetos a las clases base que voy a utilizar para las controladores y los modelos?

  • Alan perfecto este tutorial, muchos desarrolladores hoy nos quedamos con el sinsabor de no tener muchos artículos como este enfocados al uso de los diferentes frameworks, actualmente uso el Laravel y creo que de a pocos me voy auto-satisfaciendo en conocimientos para conseguir el objetivo de manejarlo y construir nuevas aplicaciones. Y obvio luego trabajar en esta área que me gusta tanto! Mi pregunta sería si tienes alguna recomendación de sites donde pueda descargar libros actualizados de programación PHP y frameworks como Codeigniter, laravel y otros, un abrazo y felicitaciones, buen site, ya la agregué a mis favoritos!

A %d blogueros les gusta esto: