Inyección de Dependencias en PHP: Guía Completa con Ejemplos

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 en PHP



El desarrollo moderno en PHP es impensable sin los principios de diseño orientado a objetos. Uno de los patrones clave que permite construir aplicaciones flexibles, testeables y mantenibles es Dependency Injection (DI) o inyección de dependencias.



La esencia del patrón es simple: en lugar de crear objetos dependientes dentro de la clase, los pasamos (inyectamos) desde el exterior. Esto cambia radicalmente la arquitectura de la aplicación, haciendo que las clases sean independientes de implementaciones concretas y simplificando su prueba.



En este artículo analizaremos qué es Dependency Injection en PHP, qué formas de implementación existen y cómo usar contenedores DI para automatizar el proceso.



El problema: ¿por qué es malo sin DI?



Consideremos un ejemplo típico. La clase UserController se encarga de procesar solicitudes relacionadas con usuarios. Utiliza la base de datos a través de la clase MysqlDatabase:



<?php

class MysqlDatabase { public function query(string $sql): array { // ... conexión a MySQL y ejecución de la consulta return []; }}

class UserController { private MysqlDatabase $database;

public function __construct() { // Acoplamiento rígido a una implementación concreta $this->database = new MysqlDatabase(); }

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

$controller = new UserController();


¿Cuáles son los problemas de este código?



  • Alto acoplamiento: UserController está fuertemente vinculado a MysqlDatabase. Si queremos migrar a PostgreSQL o usar almacenamiento en archivos, tendremos que modificar el código del controlador.
  • Dificultad para pruebas: No se puede reemplazar la base de datos por un objeto mock en pruebas unitarias. Cada prueba accederá a la base de datos real, lo cual es lento e incómodo.
  • Violación del principio de responsabilidad única: El controlador no debería saber cómo crear una conexión a la base de datos. Su tarea es procesar solicitudes.


La solución a este problema es aplicar el principio de Inversión de Control (IoC) y usar Dependency Injection.



Formas de inyectar dependencias en PHP



Existen tres formas principales de inyectar una dependencia en una clase:



1. Inyección por constructor (Constructor Injection)



La forma más común y recomendada. La dependencia se pasa a través del parámetro del constructor y generalmente se guarda como una propiedad privada de la clase.



<?php

interface DatabaseInterface { public function query(string $sql): array;}

class MysqlDatabase implements DatabaseInterface { public function query(string $sql): array { // Implementación para MySQL return []; }}

class PostgresDatabase implements DatabaseInterface { public function query(string $sql): array { // Implementación para PostgreSQL return []; }}

class UserController { private DatabaseInterface $database;

// La dependencia se inyecta a través del constructor public function __construct(DatabaseInterface $database) { $this->database = $database; }

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

// Uso$mysqlDb = new MysqlDatabase();$controller = new UserController($mysqlDb);

// Fácilmente cambiamos a otra BD$postgresDb = new PostgresDatabase();$controller2 = new UserController($postgresDb);


Ventajas: La dependencia es explícitamente visible, el objeto se crea en un estado válido (la dependencia es obligatoria).



2. Inyección por setters (Setter Injection)



Adecuada para dependencias opcionales o cuando las depend

Blogs

Book Recommendations