php 自动绑定di容器实现

  1 <?php
  2 
  3 class Bim
  4 {
  5     public function doSth()
  6     {
  7         echo __METHOD__.PHP_EOL;
  8     }
  9 }
 10 
 11 class Bar
 12 {
 13     protected $bim;
 14 
 15     public function __construct(Bim $bim)
 16     {
 17         $this->bim = $bim;
 18     }
 19 
 20     public function doSth()
 21     {
 22         $this->bim->doSth();
 23         echo __METHOD__.PHP_EOL;
 24     }
 25 }
 26 
 27 class Bar2 extends Bar
 28 {
 29     protected $bim;
 30 
 31     public function doSth()
 32     {
 33         $this->bim->doSth();
 34         echo __METHOD__.PHP_EOL;
 35     }
 36 }
 37 
 38 class Foo
 39 {
 40     private $bar;
 41 
 42     public function __construct(Bar $bar)
 43     {
 44         $this->bar = $bar;
 45     }
 46 
 47     public function doSth()
 48     {
 49         $this->bar->doSth();
 50         echo __METHOD__.PHP_EOL;
 51     }
 52 }
 53 
 54 class Container
 55 {
 56     private $s = [];
 57 
 58     public function __set($k, $c)
 59     {
 60         $this->s[$k] = $c;
 61     }
 62 
 63     public function __get($k)
 64     {
 65         return $this->s[$k]($this);
 66     }
 67 }
 68 
 69 class Container2
 70 {
 71     private $s = [];
 72 
 73     public function __set($k, $c)
 74     {
 75         $this->s[$k] = $c;
 76     }
 77 
 78     public function __get($k)
 79     {
 80         if (!$this->s[$k]) {
 81             return false;
 82         }    
 83         return $this->build($this->s[$k]);
 84     }
 85 
 86     public function build($className)
 87     {
 88         if ($className instanceof Closure) {
 89             return $className($this);
 90         }
 91 
 92         try {
 93             $reflector = new ReflectionClass($className);
 94         } catch (\ReflectionException $e) {
 95             echo $className.'类反射异常'.PHP_EOL;
 96             echo $e->getMessage();
 97         }
 98         
 99         #检查类是否可实例化, 排除抽象类abstract和对象接口interface
100         if (!$reflector->isInstantiable()) {
101             throw new Exception("Can't instantiate this.");
102         }
103 
104         $constructor = $reflector->getConstructor();
105         
106         #如果没有构造函数, 直接实例化并返回
107         if (is_null($constructor)) {
108             return new $className;
109         }
110 
111         $parameters = $constructor->getParameters();
112 
113         #递归解析构造函数的参数
114         $dependencies = $this->getDependencies($parameters);
115 
116         #创建一个类的新实例,给出的参数将传递到类的构造函数.
117         return $reflector->newInstanceArgs($dependencies);
118     }
119 
120     public function getDependencies($parameters)
121     {
122         $dependencies = [];
123 
124         foreach ($parameters as $parameter) {
125             $dependency = $parameter->getClass();
126 
127             if (is_null($dependency)) {
128                 $dependencies[] = $this->resolveNonClass($parameter);
129             } else {
130                 #是一个类,递归解析
131                 $className = lcfirst($dependency->name);
132                 #先取出容器中绑定的类 否则自动绑定
133                 if ($this->s[$className]) {
134                     $dependencies[] = $this->$className;                    
135                 } else {
136                     $dependencies[] = $this->build($dependency->name);                                        
137                 }
138             }
139         }
140 
141         return $dependencies;
142     }
143 
144     public function resolveNonClass($parameter)
145     {
146         // 有默认值则返回默认值
147         if ($parameter->isDefaultValueAvailable()) {
148             return $parameter->getDefaultValue();
149         }
150         throw new Exception('I have no idea what to do here.');
151     }
152 }
153 
154 // 依赖注入模式
155 //$foo = new Foo(new Bar(new Bim()));
156 
157 #di模式
158 // $c = new Container();
159 // $c->bim = function() {
160 //     return new Bim();
161 // };
162 // $c->bar = function($c) {
163 //     return new Bar($c->bim);
164 // };
165 // $c->foo = function($c) {
166 //     return new Foo($c->bar);
167 // };
168 
169 #实现了自动绑定
170 #1向di中注册类
171 $c = new Container2();
172 $c->bim = 'Bim';
173 #$c->bar = 'Bar2'; #实现了自动绑定 如果没有注册类的化就按自动加载去寻找类
174 $c->foo = 'Foo';
175 // $c->bar = 'Bar';
176 // $c->foo = function ($c) {
177 //     return new Foo($c->bar);
178 // };
179 // 从容器中取得Foo
180 $foo = $c->foo;
181 $foo->doSth();

参考:https://segmentfault.com/a/1190000002424023

posted @ 2016-12-05 16:57  fly不起来啊!  阅读(596)  评论(0编辑  收藏  举报