Skip to content

Instantly share code, notes, and snippets.

@tomnomnom
Created December 30, 2012 14:00
Show Gist options
  • Save tomnomnom/4412916 to your computer and use it in GitHub Desktop.
Save tomnomnom/4412916 to your computer and use it in GitHub Desktop.
An experiment: using traits for dependency injection
<?php
// An experiment: using traits for dependency injection
// A trait provides a way to inject a Logger and a way to use it
trait aLogger {
protected $logger = null;
public function setLogger(Logger $logger){
$this->logger = $logger;
}
public function log($msg){
if (is_null($this->logger)) return false;
$this->logger->log($msg);
}
}
// The logger that will be injected
class Logger {
public function log($msg){
echo $msg.PHP_EOL;
}
}
// Some other class defines that it needs to use "a Logger"
class Widget {
use aLogger;
public function test(){
echo "A test!\n";
// aLogger::log does nothing if $this->logger is null
$this->log("A log!");
}
}
// The factory for creating objects
class Factory {
// A way to get a logger; nothing special
public function newLogger(){
return new Logger();
}
// A way to get a new Widget
public function newWidget(){
$w = new Widget();
// Look for and inject dependencies
return $this->injectDeps($w);
}
protected function injectDeps($obj){
// Look up the traits the class is using
$traits = class_uses($obj);
// If the class is *use*ing aLogger, then we know to inject one
if ($traits['aLogger']){
$obj->setLogger($this->newLogger());
}
return $obj;
}
}
// Create a factory
$f = new Factory();
// Ask the factory for a new Widget; the factory will
// detect that the Widget wants "a logger" and inject one.
$w = $f->newWidget();
// Outputs "A test!\nA log!\n"
$w->test();
// We can create an object without using the factory (e.g. for testing)
// and it still "work"; it's just nothing will be logged.
$testWidget = new Widget();
// Outputs "A test!\n"
$testWidget->test();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment