Injeção de Dependência (Dependency Injection) em PHP: guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à Injeção de Dependência (DI) em PHP



O desenvolvimento moderno em PHP é impossível sem a compreensão dos princípios de baixo acoplamento entre componentes. Dependency Injection (DI), ou injeção de dependências, é um dos padrões de design chave que permite criar aplicações flexíveis, testáveis e facilmente mantíveis. Em vez de a classe criar suas próprias dependências (por exemplo, um objeto de banco de dados ou logger), ela as recebe de fora. Isso muda radicalmente a arquitetura do código.



Neste artigo, vamos detalhar o que é Dependency Injection em PHP, quais são as formas de injeção, como funciona um contêiner DI e por que esse padrão se tornou padrão para frameworks modernos, como Laravel, Symfony e Yii2.



1. O Problema: Acoplamento Rígido (Tight Coupling)



Antes de falar sobre a solução, vamos ver o problema. Um exemplo clássico é a classe UserController, que cria diretamente um objeto Database dentro de si:



<?phpclass Database {    public function query(string $sql): array {        // Conexão ao BD e execução da consulta        return [];    }}

class UserController { private Database $db;

public function __construct() { // Dependência rígida — criamos o objeto dentro do construtor $this->db = new Database(); }

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


Desvantagens dessa abordagem:

  • Dificuldade de teste: Você não conseguirá substituir Database por um objeto mock em testes unitários.
  • Violação do Princípio da Responsabilidade Única (SRP): A classe é responsável não apenas pela lógica de negócio, mas também pela criação de dependências.
  • Dificuldade de modificação: Se quiser substituir MySQL por PostgreSQL, terá que alterar o código em todas as classes onde Database é criado.


2. A Solução: Injeção de Dependências (Dependency Injection)



Dependency Injection propõe passar as dependências de fora. Existem três formas principais de injeção: via construtor, via setters e via interface (método). Vamos analisar cada uma.



2.1. Injeção via Construtor (Constructor Injection)



A forma mais comum e recomendada. As dependências são passadas uma vez na criação do objeto e não podem ser alteradas posteriormente.



<?phpclass UserController {    private Database $db;

// A dependência é passada de fora 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);?>


Vantagens: Garante que a dependência esteja sempre disponível; ideal para dependências obrigatórias. Desvantagens: Se a classe tiver muitas dependências, o construtor se torna volumoso.



2.2. Injeção via Setters (Setter Injection)



Adequado para dependências opcionais, que podem ser definidas após a criação do 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('Buscando usuários...'); } // Lógica de obtenção de usuários return []; }}

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


Vantagens:

Blogs

Book Recommendations