Inyección de Dependencias (Dependency Injection) en PHP para principiantes

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

¿Qué es Dependency Injection en PHP y por qué es necesaria?

\n\n

Imagina que estás construyendo una casa. En lugar de fabricar tú mismo cada ladrillo, simplemente los pides y usas los ya hechos. Dependency Injection (DI) en programación funciona bajo el mismo principio: no creas objetos dentro de la clase, sino que los recibes desde fuera. Esto hace que tu código sea flexible, comprobable y comprensible.

\n\n

En PHP, como en cualquier lenguaje orientado a objetos, las clases a menudo dependen de otras clases. El problema surge cuando las dependencias se crean directamente dentro de la clase; esto se llama acoplamiento rígido (tight coupling). Dependency Injection resuelve este problema pasando las dependencias desde el exterior.

\n\n

El problema sin Dependency Injection

\n

Consideremos un ejemplo típico donde la clase UserService crea ella misma el objeto de base de datos:

\n\n
<?php\nclass Database {\n    public function query($sql) {\n        // Lógica de la consulta\n        return "Resultado: " . $sql;\n    }\n}\n\nclass UserService {\n    private $db;\n    \n    public function __construct() {\n        // Acoplamiento rígido: la clase crea su propia dependencia\n        $this->db = new Database();\n    }\n    \n    public function getUser($id) {\n        return $this->db->query("SELECT * FROM users WHERE id = $id");\n    }\n}\n\n$service = new UserService();\necho $service->getUser(1);\n?>
\n\n

Problemas de este enfoque:

\n
    \n
  • No se puede reemplazar Database por otra implementación (por ejemplo, para pruebas)
  • \n
  • Difícil de probar: no se puede inyectar un simulacro (mock)
  • \n
  • El código se vuelve monolítico y difícil de ampliar
  • \n
\n\n

Solución: Inyección de dependencia a través del constructor

\n

Ahora reescribamos la misma clase usando Dependency Injection:

\n\n
<?php\nclass UserService {\n    private $db;\n    \n    // La dependencia se pasa desde el exterior\n    public function __construct(Database $db) {\n        $this->db = $db;\n    }\n    \n    public function getUser($id) {\n        return $this->db->query("SELECT * FROM users WHERE id = $id");\n    }\n}\n\n// Creamos la dependencia por separado\n$database = new Database();\n$service = new UserService($database);\necho $service->getUser(1);\n?>
\n\n

Ahora UserService no sabe cómo se crea Database. Simplemente usa lo que le pasaron. Esto es inyección de dependencia.

\n\n

Tipos de Dependency Injection en PHP

\n

Existen tres formas principales de inyectar dependencias. Veamos cada una con ejemplos.

\n\n

1. Inyección por constructor (Constructor Injection)

\n

La forma más común y recomendada. Las dependencias se pasan al crear el objeto a través del constructor.

\n\n
<?php\nclass Logger {\n    public function log($message) {\n        echo "[LOG]: " . $message;\n    }\n}\n\nclass OrderProcessor {\n    private $logger;\n    \n    // Dependencia en el constructor\n    public function __construct(Logger $logger) {\n        $this->logger = $logger;\n    }\n    \n    public function process($order) {\n        // Procesamiento del pedido\n        $this->logger->log("Pedido procesado: " . $order);\n    }\n}\n\n$logger = new Logger();\n$processor = new OrderProcessor($logger);\n$processor->process("Pedido #123");\n?>
\n\n

Ventajas: la dependencia siempre está disponible, el objeto siempre está en un estado válido. Desventajas: si hay muchas dependencias, el constructor puede volverse voluminoso.

\n\n

2. Inyección por setter (Setter Injection)

\n

Se usa cuando la dependencia puede ser opcional o necesita ser reemplazada durante la vida del objeto.

\n\n
<?php\nclass MailService {\n    private $transport;\n    \n    // Setter para la dependencia\n    public function setTransport($transport) {\n        $this->transport = $transport;\n    }\n    \n    public function send($to, $mess                

Blogs

Book Recommendations