Milind Daraniya

Dependency Injection in PHP: Explained with Examples

Published January 21st, 2023 18 min read

Dependency Injection is a powerful design pattern in PHP that promotes loose coupling between classes, making your code more maintainable and testable. By injecting dependencies into classes instead of creating them inside the class, you achieve better separation of concerns and increase the reusability of your code. In this post, we'll delve into the concept of Dependency Injection in PHP and explore practical examples to understand its benefits.

Understanding Dependency Injection

Dependency Injection is a technique where a class receives its dependencies from the outside, rather than creating them internally. This way, a class does not need to be aware of how to instantiate its dependencies, enabling flexibility and ease of testing.

Consider a classic example of a User class that requires a Logger:

class User
{
    private $logger;

    public function __construct()
    {
        $this->logger = new Logger();
    }

    public function register()
    {
        // Registration logic

        // Logging the registration event
        $this->logger->log('User registered successfully.');
    }
}

In this example, the User class creates its own Logger instance, leading to tight coupling between the two classes. Testing the User class becomes difficult, as the Logger is hardcoded inside it.

Dependency Injection to the Rescue

Let's rewrite the User class using Dependency Injection:

class User
{
    private $logger;

    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
    }

    public function register()
    {
        // Registration logic

        // Logging the registration event
        $this->logger->log('User registered successfully.');
    }
}

Now, the User class receives the Logger instance via its constructor, decoupling it from the specific implementation of the logger. This allows us to inject different loggers, making the class more flexible and testable.

Using Dependency Injection Containers

A Dependency Injection Container (DIC) is a powerful tool that manages class dependencies and their instantiation. It automates the process of creating and injecting dependencies, reducing the boilerplate code in your application.

Example of a simple DIC in PHP:

class Container
{
    private $services = [];

    public function addService($key, $value)
    {
        $this->services[$key] = $value;
    }

    public function getService($key)
    {
        return $this->services[$key]();
    }
}

Implementing Dependency Injection with DIC

Let's use the DIC to inject the Logger into the User class:

$container = new Container();

$container->addService('logger', function () {
    return new Logger();
});

$user = new User($container->getService('logger'));
$user->register();

In this example, the DIC manages the Logger instance, and we inject it into the User class. Now, we can easily replace the Logger with a different logging implementation by modifying the DIC configuration.

Dependency Injection is a powerful design pattern that promotes flexibility, testability, and maintainability in PHP applications. By decoupling classes from their dependencies, you create code that is easier to manage, extend, and test.

Using a Dependency Injection Container further streamlines the process of managing class dependencies, reducing boilerplate code and simplifying the injection of dependencies.

Incorporate Dependency Injection into your PHP projects, and you'll discover its potential to elevate your application architecture and development practices to new heights.