2.6. Dependency Injection

2.6.1. Rôle

Implémenter une architecture faiblement couplée afin d’obtenir une meilleur testabilité, maintenabilité et extensibilité du code.

2.6.2. Usage

DatabaseConfiguration est injectée et DatabaseConnexion obtiendra tout ce dont elle a besoin à partir de $config. Sans DI, la configuration serait créée directement dans DatabaseConnexion, ce qui n’est pas très bon pour les tests et les extensions.

2.6.3. Exemples

  • L’ORM Doctrine2 utilise l’injection de dépendances, par exemple pour la configuration qui est injectée dans un objet Connexion. À des fins de test, on peut facilement créer un objet fantaisie de la configuration et l’injecter dans l’objet Connexion.

  • De nombreux frameworks disposent déjà de conteneurs pour DI qui créent des objets via un tableau de configuration et les injectent là où c’est nécessaire (c’est-à-dire dans les contrôleurs).

2.6.4. Diagramme UML

Alt DependencyInjection UML Diagram

2.6.5. Code

Vous pouvez également trouver ce code sur GitHub

DatabaseConfiguration.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\DependencyInjection;
 6
 7class DatabaseConfiguration
 8{
 9    public function __construct(
10        private string $host,
11        private int $port,
12        private string $username,
13        private string $password
14    ) {
15    }
16
17    public function getHost(): string
18    {
19        return $this->host;
20    }
21
22    public function getPort(): int
23    {
24        return $this->port;
25    }
26
27    public function getUsername(): string
28    {
29        return $this->username;
30    }
31
32    public function getPassword(): string
33    {
34        return $this->password;
35    }
36}

DatabaseConnection.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\DependencyInjection;
 6
 7class DatabaseConnection
 8{
 9    public function __construct(private DatabaseConfiguration $configuration)
10    {
11    }
12
13    public function getDsn(): string
14    {
15        // this is just for the sake of demonstration, not a real DSN
16        // notice that only the injected config is used here, so there is
17        // a real separation of concerns here
18
19        return sprintf(
20            '%s:%s@%s:%d',
21            $this->configuration->getUsername(),
22            $this->configuration->getPassword(),
23            $this->configuration->getHost(),
24            $this->configuration->getPort()
25        );
26    }
27}

2.6.6. Test

Tests/DependencyInjectionTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\DependencyInjection\Tests;
 6
 7use DesignPatterns\Structural\DependencyInjection\DatabaseConfiguration;
 8use DesignPatterns\Structural\DependencyInjection\DatabaseConnection;
 9use PHPUnit\Framework\TestCase;
10
11class DependencyInjectionTest extends TestCase
12{
13    public function testDependencyInjection()
14    {
15        $config = new DatabaseConfiguration('localhost', 3306, 'user', '1234');
16        $connection = new DatabaseConnection($config);
17
18        $this->assertSame('user:1234@localhost:3306', $connection->getDsn());
19    }
20}