PHP Setter Injection


Exemple

Les dépendances peuvent également être injectées par les installateurs.

interface Logger {
    public function log($message);
}

class Component {
    private $logger;
    private $databaseConnection;

    public function __construct(DatabaseConnection $databaseConnection) {
        $this->databaseConnection = $databaseConnection;
    }

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

    public function core() {
        $this->logSave();    
        return $this->databaseConnection->save($this);
    }

    public function logSave() {
         if ($this->logger) {
            $this->logger->log('saving');
        }
    }
}

Ceci est particulièrement intéressant lorsque la fonctionnalité principale de la classe ne repose pas sur la dépendance au travail.

Ici, la seule dépendance nécessaire est la DatabaseConnection , elle se trouve donc dans le constructeur. La dépendance Logger est facultative et n'a donc pas besoin de faire partie du constructeur, ce qui facilite son utilisation.

Notez que lors de l'utilisation de l'injection par setter, il est préférable d'étendre la fonctionnalité plutôt que de la remplacer. Lors de la définition d'une dépendance, rien ne permet de confirmer que la dépendance ne changera pas à un moment donné, ce qui pourrait entraîner des résultats inattendus. Par exemple, un FileLogger pourrait être défini au préalable, puis un MailLogger pourrait être défini. Ce casse encapsulation et rend difficile de trouver des journaux, parce que nous remplaçons la dépendance.

Pour éviter cela, nous devrions ajouter une dépendance avec l'injection de setter, comme ceci:

interface Logger {
    public function log($message);
}

class Component {
    private $loggers = array();
    private $databaseConnection;

    public function __construct(DatabaseConnection $databaseConnection) {
        $this->databaseConnection = $databaseConnection;
    }

    public function addLogger(Logger $logger) {
        $this->loggers[] = $logger;
    }

    public function core() {
        $this->logSave();
        return $this->databaseConnection->save($this);
    }

    public function logSave() {
        foreach ($this->loggers as $logger) {
            $logger->log('saving');
        }
    }
}

Comme cela, chaque fois que nous utiliserons les fonctionnalités de base, elles ne seront pas endommagées même si aucune dépendance de l'enregistreur n'est ajoutée, et tout enregistreur ajouté sera utilisé même si un autre enregistreur a pu être ajouté. Nous étendons la fonctionnalité au lieu de la remplacer .