纸上得来终觉浅,得知此事需躬行。
之前看phalcon框架DI的实现方式,觉得很好用,但是由于是c扩展,看不了源码,并不知道是如何实现的,后来看laravel的服务容器,发现是实现了php的SPL接口,然后用这些接口实现的。
一个典型的「container」便是实现了arrayaccess,Demo如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| <?php namespace skylee;
class A { public function say() { return __METHOD__; } }
class B {
public function say() { return __METHOD__; } }
class Container implements \arrayaccess {
private $container = array();
public function __construct(array $array = []) { $this->container = $array; }
public function __get($id) { return $this->offsetGet($id); }
public function offsetSet($offset, $value) { if (is_null($offset)) { $this->container[] = $value; } else { $this->container[$offset] = $value; } }
public function offsetExists($offset) { return isset($this->container[$offset]); }
public function offsetUnset($offset) { unset($this->container[$offset]); }
public function offsetGet($offset) { $raw = $this->container[$offset]; return $this->container[$offset] = $raw(); } public function register($Manage) { $Manage->register($this); } }
interface ServiceProvide { public function register(Container $container); }
class ProvideA implements ServiceProvide { public function register(Container $container) { $container['A'] = function () { return new skylee\A; }; } }
class ProvideB implements ServiceProvide { public function register(Container $container) { $container['B'] = function () { return new skylee\B; }; } }
class App extends Container { public $service = [ skylee\ProvideA::class, skylee\ProvideB::class ]; public function __construct() { parent::__construct(); $this->registerProvide(); } public function registerProvide() { foreach ($this->service as $v) { $this->register(new $v()); } } }
$obj = new App();
$a = $obj["A"]->say();
$b = $obj["B"]->say();
var_dump($a);
var_dump($b);
|