What is Dependency Injection in PHP and why is it needed?
\n\nImagine you are building a house. Instead of making every brick yourself, you simply order them and use the ready-made ones. Dependency Injection (DI) in programming works on the same principle — you don't create objects inside a class, you receive them from the outside. This makes your code flexible, testable, and understandable.
\n\nIn PHP, as in any object-oriented language, classes often depend on other classes. The problem arises when dependencies are created directly inside the class — this is called tight coupling. Dependency Injection solves this problem by passing dependencies from the outside.
\n\nThe problem without Dependency Injection
\nConsider a typical example where the UserService class creates a database object itself:
<?php\nclass Database {\n public function query($sql) {\n // Query logic\n return "Result: " . $sql;\n }\n}\n\nclass UserService {\n private $db;\n \n public function __construct() {\n // Tight coupling — the class creates the dependency itself\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\nProblems with this approach:
\n- \n
- Cannot replace
Databasewith another implementation (e.g., for testing) \n - Difficult to test — cannot substitute a mock \n
- The code becomes monolithic and hard to extend \n
Solution: Constructor Injection
\nNow let's rewrite the same class using Dependency Injection:
\n\n<?php\nclass UserService {\n private $db;\n \n // Dependency is passed from the outside\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// Create the dependency separately\n$database = new Database();\n$service = new UserService($database);\necho $service->getUser(1);\n?>\n\nNow UserService doesn't know how Database is created. It simply uses what was passed to it. This is dependency injection.
Types of Dependency Injection in PHP
\nThere are three main ways to inject dependencies. Let's look at each with examples.
\n\n1. Constructor Injection
\nThe most common and recommended method. Dependencies are passed when creating an object through the 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 // Dependency in the constructor\n public function __construct(Logger $logger) {\n $this->logger = $logger;\n }\n \n public function process($order) {\n // Order processing\n $this->logger->log("Order processed: " . $order);\n }\n}\n\n$logger = new Logger();\n$processor = new OrderProcessor($logger);\n$processor->process("Order #123");\n?>\n\nPros: dependency is always available, the object is always in a valid state. Cons: if there are many dependencies, the constructor can become bulky.
\n\n2. Setter Injection
\nUsed when a dependency may be optional or needs to be replaced during the object's lifecycle.
\n\n<?php\nclass MailService {\n private $transport;\n \n // Setter for the dependency\n public function setTransport($transport) {\n $this->transport = $transport;\n }\n \n public function send($to, $mess