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
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php declare(strict_types=1);

namespace DesignPatterns\Structural\DependencyInjection;

class DatabaseConfiguration
{
    private string $host;
    private int $port;
    private string $username;
    private string $password;

    public function __construct(string $host, int $port, string $username, string $password)
    {
        $this->host = $host;
        $this->port = $port;
        $this->username = $username;
        $this->password = $password;
    }

    public function getHost(): string
    {
        return $this->host;
    }

    public function getPort(): int
    {
        return $this->port;
    }

    public function getUsername(): string
    {
        return $this->username;
    }

    public function getPassword(): string
    {
        return $this->password;
    }
}

DatabaseConnection.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php declare(strict_types=1);

namespace DesignPatterns\Structural\DependencyInjection;

class DatabaseConnection
{
    private DatabaseConfiguration $configuration;

    public function __construct(DatabaseConfiguration $config)
    {
        $this->configuration = $config;
    }

    public function getDsn(): string
    {
        // this is just for the sake of demonstration, not a real DSN
        // notice that only the injected config is used here, so there is
        // a real separation of concerns here

        return sprintf(
            '%s:%s@%s:%d',
            $this->configuration->getUsername(),
            $this->configuration->getPassword(),
            $this->configuration->getHost(),
            $this->configuration->getPort()
        );
    }
}

2.6.6. Test

Tests/DependencyInjectionTest.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php declare(strict_types=1);

namespace DesignPatterns\Structural\DependencyInjection\Tests;

use DesignPatterns\Structural\DependencyInjection\DatabaseConfiguration;
use DesignPatterns\Structural\DependencyInjection\DatabaseConnection;
use PHPUnit\Framework\TestCase;

class DependencyInjectionTest extends TestCase
{
    public function testDependencyInjection()
    {
        $config = new DatabaseConfiguration('localhost', 3306, 'domnikl', '1234');
        $connection = new DatabaseConnection($config);

        $this->assertSame('domnikl:1234@localhost:3306', $connection->getDsn());
    }
}