Created
December 30, 2012 14:00
-
-
Save tomnomnom/4412916 to your computer and use it in GitHub Desktop.
An experiment: using traits for dependency injection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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