08-03-2026

Contenedor de dependencias con php

Un contenedor de dependencias, o Dependency Injection Container, es una herramienta o clase especial que se encarga de:
  • Crear (instanciar) los objetos de tu aplicación.
  • Resolver automáticamente todas las dependencias que esos objetos necesitan (es decir, pasarles por el constructor o setters lo que requieren).
  • Gestionar cómo y cuándo se crean esos objetos (¿siempre uno nuevo? ¿el mismo para toda la app? ¿solo cuando se necesita realmente?).
Es como una fábrica inteligente automática que arma todos los "ladrillos" (clases/servicios) de la aplicación y les pone exactamente las piezas que necesitan, sin nadie tenga que hacerlo a mano en cada rincón del código.

Inyección de Dependencias vs Contenedor de Dependencias

  • Inyección de Dependencias: Es un patrón de diseño. Consiste en no crear las dependencias dentro de una clase, sino recibirlas desde fuera (por constructor, setter, interfaz, etc.) .Ejemplo básico sin contenedor:

    class UserService {
    private $logger;
    
    public function __construct(Logger $logger) {  // ← inyección por constructor
    $this->logger = $logger;
    }
    }
    
  • Contenedor de dependencias: Es la herramienta que hace la inyección automáticamente por ti. Se le dices (o configura automáticamente) qué clases existen y cómo se relacionan, y el contenedor se encarga del resto.

    logger = $logger;
    }
    
    public function send(string $to, string $subject) {
    $this->logger->info("Enviando email a $to: $subject");
    // envío real...
    }
    }
    // Esta clase necesita un Logger para funcionar, por eso lo recibe en el constructor (inyección de dependencias).
    //Esta clase necesita un EmailService → también lo recibe por constructor.
    
    class UserService {
    private $emailService;
    
    public function __construct(EmailService $emailService) {
    $this->emailService = $emailService;
    }
    
    public function register(string $email) {
    $this->emailService->send($email, "Bienvenido!");
    }
    }
    
    // ------------------- Contenedor muy básico -------------------
    //$services es un array donde guardamos fábricas (funciones que saben cómo crear cada //objeto)
    //La clave ($id) es un string que identifica el servicio (ej: 'logger', 'email.service')
    //El valor es una función (callable) que cuando se ejecute, crea la instancia
    
    class Container {
    private array $services = [];
    
    public function set(string $id, callable $factory): void {
    $this->services[$id] = $factory;
    }
    
    public function get(string $id) {
    if (!isset($this->services[$id])) {
      throw new Exception("Servicio '$id' no encontrado");
    }
    
    // Lazy loading + singleton simple
    static $instances = [];
    if (!isset($instances[$id])) {
      $instances[$id] = $this->services[$id]($this);
    }
    return $instances[$id];
    }
    }
    
    //Cómo se configuran / registran los servicios
    
    $container = new Container();
    
    $container->set('logger', fn() => new Logger());
    $container->set('email.service', fn($c) => new EmailService($c->get('logger')));
    $container->set('user.service', fn($c) => new UserService($c->get('email.service')));
    
    // En tu aplicación (controlador, comando, etc)
    //Uso real en la aplicación
    
    $userService = $container->get('user.service');
    $userService->register('juan@example.com');
    

Ventajas principales de usar un contenedor

  • Código mucho más limpio y sin "new" por todos lados.
  • Muy fácil cambiar implementaciones (ej: cambiar de FileLogger a DatabaseLogger sin tocar el resto del código).
  • Testing súper sencillo (inyectas mocks/fakes fácilmente).
  • Gestión automática de scopes (singleton, por-request, prototype/transient...).
  • Reduce el acoplamiento fuerte entre clases.
  • La app se vuelve más modular y mantenible.

Los contenedores más populares

Framework / Librería Contenedor propio Nivel de autowiring (automático) Uso típico
Laravel Illuminate\Container Excelente Proyectos Laravel
Symfony symfony/dependency-injection Muy bueno Proyectos Symfony
PHP-DI php-di/php-di Uno de los mejores Cualquier proyecto
Laminas / Mezzio laminas/laminas-servicemanager Bueno Apps enterprise
Yii 2/3 Contenedor integrado Bueno Proyectos Yii