O que é Dependency Injection em PHP e por que é necessário?
\n\nImagine que você está construindo uma casa. Em vez de fazer cada tijolo você mesmo, você simplesmente os encomenda e usa os prontos. Dependency Injection (DI) na programação funciona pelo mesmo princípio — você não cria objetos dentro da classe, mas os recebe de fora. Isso torna seu código flexível, testável e compreensível.
\n\nEm PHP, como em qualquer linguagem orientada a objetos, as classes frequentemente dependem de outras classes. O problema surge quando as dependências são criadas diretamente dentro da classe — isso é chamado de acoplamento rígido (tight coupling). O Dependency Injection resolve esse problema passando as dependências de fora.
\n\nProblema sem Dependency Injection
\nVamos considerar um exemplo típico onde a classe UserService cria ela mesma o objeto do banco de dados:
<?php\nclass Database {\n public function query($sql) {\n // Lógica da consulta\n return "Resultado: " . $sql;\n }\n}\n\nclass UserService {\n private $db;\n \n public function __construct() {\n // Acoplamento rígido — a classe cria a dependência\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\nProblemas dessa abordagem:
\n- \n
- Não é possível substituir
Databasepor outra implementação (por exemplo, para testes) \n - Difícil de testar — não é possível usar um mock (simulação) \n
- O código se torna monolítico e difícil de estender \n
Solução: Injeção de dependência via construtor
\nAgora vamos reescrever a mesma classe usando Dependency Injection:
\n\n<?php\nclass UserService {\n private $db;\n \n // A dependência é passada de fora\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// Criamos a dependência separadamente\n$database = new Database();\n$service = new UserService($database);\necho $service->getUser(1);\n?>\n\nAgora UserService não sabe como Database é criado. Ele simplesmente usa o que foi passado para ele. Isso é injeção de dependência.
Tipos de Dependency Injection em PHP
\nExistem três formas principais de injetar dependências. Vamos ver cada uma com exemplos.
\n\n1. Injeção via construtor (Constructor Injection)
\nA forma mais comum e recomendada. As dependências são passadas na criação do objeto através do construtor.
\n\n<?php\nclass Logger {\n public function log($message) {\n echo "[LOG]: " . $message;\n }\n}\n\nclass OrderProcessor {\n private $logger;\n \n // Dependência no construtor\n public function __construct(Logger $logger) {\n $this->logger = $logger;\n }\n \n public function process($order) {\n // Processamento do pedido\n $this->logger->log("Pedido processado: " . $order);\n }\n}\n\n$logger = new Logger();\n$processor = new OrderProcessor($logger);\n$processor->process("Pedido #123");\n?>\n\nVantagens: a dependência está sempre disponível, o objeto está sempre em estado válido. Desvantagens: se houver muitas dependências, o construtor pode se tornar extenso.
\n\n2. Injeção via setter (Setter Injection)
\nUsada quando a dependência pode ser opcional ou precisa ser alterada durante a execução do objeto.
\n\n<?php\nclass MailService {\n private $transport;\n \n // Setter para a dependência\n public function setTransport($transport) {\n $this->transport = $transport;\n }\n \n public function send($to, $mess