PHP Traits pour faciliter la réutilisation du code horizontal


Exemple

Disons que nous avons une interface pour la journalisation:

interface Logger {
    function log($message);
}

Maintenant, disons que nous avons deux implémentations concrètes de l'interface Logger : FileLogger et ConsoleLogger .

class FileLogger implements Logger {
    public function log($message) {
        // Append log message to some file
    }
}

class ConsoleLogger implements Logger {
    public function log($message) {
        // Log message to the console
    }
}

Maintenant, si vous définissez une autre classe Foo que vous voulez également pouvoir exécuter des tâches de journalisation, vous pouvez faire quelque chose comme ceci:

class Foo implements Logger {
    private $logger;

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

    public function log($message) {
        if ($this->logger) {
            $this->logger->log($message);
        }
    }
}

Foo est maintenant un Logger , mais sa fonctionnalité dépend de l'implémentation de Logger via setLogger() . Si nous voulons maintenant que class Bar également ce mécanisme de journalisation, nous devrions dupliquer ce morceau de logique dans la classe Bar .

Au lieu de dupliquer le code, un trait peut être défini:

trait LoggableTrait {
    protected $logger;

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

    public function log($message) {
        if ($this->logger) {
            $this->logger->log($message);
        }
    }
}

Maintenant que nous avons défini la logique dans un trait, nous pouvons utiliser le trait pour ajouter la logique aux classes Foo et Bar :

class Foo {
    use LoggableTrait;
}

class Bar {
    use LoggableTrait;
}

Et, par exemple, nous pouvons utiliser la classe Foo comme ceci:

$foo = new Foo();
$foo->setLogger( new FileLogger() );

//note how we use the trait as a 'proxy' to call the Logger's log method on the Foo instance
$foo->log('my beautiful message');