Dependency Injection in PHP: A Simple Guide 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

Dependency Injection in PHP: For Beginners



Imagine you are assembling a computer. You don't solder the processor directly onto the motherboard forever — you insert it into a special socket so you can replace it with a more powerful one if needed. Dependency Injection (DI) in PHP works on the same principle: instead of creating dependencies inside a class, you "inject" them from the outside.



In this article, we will break down what Dependency Injection is, why it is needed, and how to apply it in PHP. You will learn how to make your code flexible, testable, and easy to maintain.



What is Dependency Injection in Simple Terms



Dependency Injection is a design pattern where an object receives its dependencies (other objects, services) from the outside, rather than creating them itself. Instead of writing new Database() inside a class, you pass a ready-made database object through the constructor or a setter.



Let's look at the problem that DI solves. Consider the UserService class, which directly creates a database connection:



<?phpclass UserService {    private $db;        public function __construct() {        // Tight coupling to a specific implementation        $this->db = new MySQLConnection('localhost', 'user', 'pass');    }        public function getUser($id) {        return $this->db->query("SELECT * FROM users WHERE id = $id");    }}?>


The problems with this approach are obvious:



  • Tight coupling — the UserService class is tied to MySQLConnection. To switch to PostgreSQL, you would have to change the class code.
  • Difficulty in testing — you cannot replace the database with a mock object in unit tests.
  • Violation of the Single Responsibility Principle — the class is not only responsible for working with users but also for creating the database connection.


Now let's rewrite this class using Dependency Injection:



<?phpinterface DatabaseInterface {    public function query($sql);}

class MySQLConnection implements DatabaseInterface { public function query($sql) { // Implementation for MySQL }}

class PostgreSQLConnection implements DatabaseInterface { public function query($sql) { // Implementation for PostgreSQL }}

class UserService { private $db; // Dependency is injected via the constructor public function __construct(DatabaseInterface $db) { $this->db = $db; } public function getUser($id) { return $this->db->query("SELECT * FROM users WHERE id = $id"); }}

// Usage$db = new MySQLConnection('localhost', 'user', 'pass');$userService = new UserService($db);?>


Now UserService doesn't know which specific database it is working with. It simply uses the DatabaseInterface interface. This is the essence of Dependency Injection.



Three Main Types of Dependency Injection



In PHP, there are three main ways to inject dependencies. Let's look at each one.



1. Constructor Injection



This is the most common and recommended method. Dependencies are passed through the constructor parameters and stored in the class's private properties.



<?phpclass Logger {    private $writer;        public function __construct(LogWriterInterface $writer) {        $this->writer = $writer;    }        public function log($message) {        $this->writer->write($message);    }}?>


Pros: dependencies are clearly visible, the object is always in a valid state (all dependencies are mandatory).



Cons: e

Blogs

Book Recommendations