L'injection de dépendances

Bonjour,

Je voulais revenir sur un mécanisme que vous rencontrerez souvent lorsque vous développerez en poo, l'injection de dépendances.

Cette technique permet non seulement d'assurer une meilleure lisibilité mais aussi une meilleure maintenance.

Il existe plusieurs types d'injections de dépendances, nous en détaillerons les principales:

  • Injection par constructeur
  • Injection par mutateur
  • Injection par interface
  • ...

Nous voulons associer à une classe Post la classe Auteur:

Sans injection de dépendance


class Post {
    public function __construct($fullname, $website, $email) {
        $this->setFullname($fullname);
        $this->setWebsite($website);
        $this->setEmail($email);
    }

    public function setFullname($fullname) {
        $this->fullname = $fullname;
    }

    public function setWebsite($website) {
        $this->website = $website;
    }

    public function setEmail($email) {
        $this->email = $email;
    }
}

Nous constatons que les deux classes sont intimement liées. A chaque ajout de champ dans la classe Author, nous devons ajuster le constructeur de Post !

Voyons comment faire autrement:

Injection par contructeur

use Author;

class Post {
    public function __construct(Author $author) {
        $this->setAuthor($author);
    }

    public function setAuthor(Author $author) {
        $this->author = $author;
    }

    public function getAuthor() {
        return $this->author;
    }
}

Ici, on doit instancer une instance de la classe Author avant d'instancier la classe Post.

Injection par mutateur

use Author;

class Post {
    public function __construct() {

    }

    public function setAuthor(Author $author) {
        $this->author = $author;
    }

    public function getAuthor() {
        return $this->author;
    }
}

Ici, on doit utiliser le mutateur pour associer les classes.

Injection par interface

interface AuthorInterface {
    public function getFullname();
    public function getWebsite();
    public function getEmail();
    // ...
}
class Author implements AuthorInterface {
    public function getFullname() {
        return $this->fullname;
    }
    public function getWebsite() {
        return $this->website;
    }
    public function getEmail() {
        return $this->email;
    }
    // D'autres choses...
}
use AuthorInterface;

class Post {
    public function __construct(AuthorInterface $author) {
        $this->setAuthor($author);
    }
}

Il existe d'autres méthodes pour réaliser une injection de dépendances plus pratique et plus robuste à utiliser.

Le framework Symfony, depuis sa version 3.3, utilise les conteneurs PSR-11.

Depuis la doc :

Dans Symfony, ces objets utiles sont appelés services et chaque service réside dans un objet très spécial appelé conteneur de services. Si vous avez le conteneur de service, vous pouvez récupérer un service en utilisant l'identifiant de ce service:

$logger = $container->get('logger');
$entityManager = $container->get('doctrine.orm.entity_manager');

Le conteneur vous permet de centraliser la manière dont les objets sont construits. Cela vous facilite la vie, favorise une architecture forte et est super rapide!

Pour aller plus loin

A très bientôt,

Weenesta