Dependency Injection in PHP for Beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What is Dependency Injection in PHP and why is it needed?

\n\n

Imagine 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\n

In 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\n

The problem without Dependency Injection

\n

Consider a typical example where the UserService class creates a database object itself:

\n\n
<?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\n

Problems with this approach:

\n
    \n
  • Cannot replace Database with another implementation (e.g., for testing)
  • \n
  • Difficult to test — cannot substitute a mock
  • \n
  • The code becomes monolithic and hard to extend
  • \n
\n\n

Solution: Constructor Injection

\n

Now 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\n

Now UserService doesn't know how Database is created. It simply uses what was passed to it. This is dependency injection.

\n\n

Types of Dependency Injection in PHP

\n

There are three main ways to inject dependencies. Let's look at each with examples.

\n\n

1. Constructor Injection

\n

The 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\n

Pros: dependency is always available, the object is always in a valid state. Cons: if there are many dependencies, the constructor can become bulky.

\n\n

2. Setter Injection

\n

Used 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                

Blogs

Book Recommendations