Inyección de Dependencias (Dependency Injection) en PHP: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción a Dependency Injection (DI) en PHP



El desarrollo moderno en PHP es imposible sin comprender los principios de bajo acoplamiento entre componentes. Dependency Injection (DI), o inyección de dependencias, es uno de los patrones de diseño clave que permite crear aplicaciones flexibles, testeables y fácilmente mantenibles. En lugar de que una clase cree sus propias dependencias (por ejemplo, un objeto de base de datos o un logger), las recibe desde el exterior. Esto cambia radicalmente la arquitectura del código.



En este artículo, analizaremos en detalle qué es Dependency Injection en PHP, cuáles son las formas de inyección, cómo funciona un contenedor DI y por qué este patrón se ha convertido en el estándar para frameworks modernos como Laravel, Symfony y Yii2.



1. El problema: Alto acoplamiento (Tight Coupling)



Antes de hablar de la solución, veamos el problema. Un ejemplo clásico es la clase UserController, que crea directamente un objeto Database dentro de sí misma:



<?phpclass Database {    public function query(string $sql): array {        // Conexión a la BD y ejecución de la consulta        return [];    }}

class UserController { private Database $db;

public function __construct() { // Dependencia rígida: creamos el objeto dentro del constructor $this->db = new Database(); }

public function getUsers(): array { return $this->db->query('SELECT * FROM users'); }}?>


Desventajas de este enfoque:

  • Dificultad para realizar pruebas: No se puede reemplazar Database por un objeto mock en pruebas unitarias.
  • Violación del principio de responsabilidad única (SRP): La clase no solo se encarga de la lógica de negocio, sino también de crear sus dependencias.
  • Dificultad de modificación: Si se desea cambiar MySQL por PostgreSQL, habría que modificar el código en todas las clases donde se crea Database.


2. La solución: Inyección de dependencias (Dependency Injection)



Dependency Injection propone pasar las dependencias desde el exterior. Existen tres formas principales de inyección: a través del constructor, a través de setters y a través de una interfaz (método). Analicemos cada una.



2.1. Inyección por constructor (Constructor Injection)



Es la forma más común y recomendada. Las dependencias se pasan una sola vez al crear el objeto y no pueden modificarse posteriormente.



<?phpclass UserController {    private Database $db;

// La dependencia se pasa desde el exterior public function __construct(Database $db) { $this->db = $db; }

public function getUsers(): array { return $this->db->query('SELECT * FROM users'); }}

// Uso:$db = new Database();$controller = new UserController($db);?>


Ventajas: Garantiza que la dependencia siempre esté disponible; es ideal para dependencias obligatorias. Desventajas: Si la clase tiene muchas dependencias, el constructor se vuelve voluminoso.



2.2. Inyección por setters (Setter Injection)



Es adecuada para dependencias opcionales que pueden establecerse después de crear el objeto.



<?phpclass Logger {    public function log(string $message): void {        echo $message;    }}

class UserController { private ?Logger $logger = null;

public function setLogger(Logger $logger): void { $this->logger = $logger; }

public function getUsers(): array { if ($this->logger) { $this->logger->log('Obteniendo usuarios...'); } // Lógica para obtener usuarios return []; }}

// Uso:$controller = new UserController();$controller->setLogger(new Logger());?>


Ventajas:

Blogs

Book Recommendations