1 | <?php |
||
12 | class Container implements ArrayAccess |
||
13 | { |
||
14 | // 容器对象实例 |
||
15 | protected static $instance; |
||
16 | // 容器中的对象实例 |
||
17 | protected $instances=[]; |
||
18 | // 容器中绑定的对象标识 |
||
19 | protected $bind=[]; |
||
20 | |||
21 | /** |
||
22 | * 获取当前容器的实例(单例) |
||
23 | * @access public |
||
24 | * @return \puck\Container |
||
25 | */ |
||
26 | 3 | public static function getInstance() |
|
27 | { |
||
28 | 3 | if (is_null(static::$instance)) { |
|
29 | static::$instance=new static; |
||
30 | } |
||
31 | |||
32 | 3 | return static::$instance; |
|
33 | } |
||
34 | |||
35 | |||
36 | /** |
||
37 | * 设置共享容器实例 |
||
38 | * @param ArrayAccess $container |
||
39 | * @return static |
||
40 | */ |
||
41 | public static function setInstance(ArrayAccess $container) |
||
45 | |||
46 | /** |
||
47 | * 绑定一个类到容器 |
||
48 | * @access public |
||
49 | * @param string $abstract 类标识、接口 |
||
50 | * @param string|\Closure $concrete 要绑定的类或者闭包 |
||
51 | * @return void |
||
52 | */ |
||
53 | public function bind($abstract, $concrete=null) |
||
61 | |||
62 | /** |
||
63 | * 绑定一个类实例当容器 |
||
64 | * @access public |
||
65 | * @param string $abstract 类名或者标识 |
||
66 | * @param object $instance 类的实例 |
||
67 | * @return void |
||
68 | */ |
||
69 | public function instance($abstract, $instance) |
||
73 | |||
74 | /** |
||
75 | * 判断容器中是否存在类及标识 |
||
76 | * @access public |
||
77 | * @param string $abstract 类名或者标识 |
||
78 | * @return bool |
||
79 | */ |
||
80 | public function bound($abstract) |
||
81 | { |
||
82 | return isset($this->bind[$abstract]) || isset($this->instances[$abstract]); |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * 创建类的实例 |
||
87 | * @access public |
||
88 | * @param array $vars 变量 |
||
89 | * @return object |
||
90 | */ |
||
91 | 2 | public function make($abstract, $vars=[]) |
|
92 | { |
||
93 | 2 | if (isset($this->instances[$abstract])) { |
|
94 | 1 | $object=$this->instances[$abstract]; |
|
95 | 2 | } elseif (isset($this->bind[$abstract])) { |
|
96 | 1 | $concrete=$this->bind[$abstract]; |
|
97 | 1 | if ($concrete instanceof \Closure) { |
|
98 | $object=call_user_func_array($concrete, $vars); |
||
99 | } else { |
||
100 | 1 | $object=$this->make($concrete, $vars); |
|
101 | } |
||
102 | } else { |
||
103 | 1 | $object=$this->invokeClass($abstract, $vars); |
|
104 | |||
105 | 1 | $this->instances[$abstract]=$object; |
|
106 | } |
||
107 | 2 | return $object; |
|
108 | } |
||
109 | |||
110 | /** |
||
111 | * 执行函数或者闭包方法 支持参数调用 |
||
112 | * @access public |
||
113 | * @param \Closure $function 函数或者闭包 |
||
114 | * @param array $vars 变量 |
||
115 | * @return mixed |
||
116 | */ |
||
117 | public function invokeFunction($function, $vars=[]) |
||
123 | |||
124 | /** |
||
125 | * 调用反射执行类的方法 支持参数绑定 |
||
126 | * @access public |
||
127 | * @param string|array $method 方法 |
||
128 | * @param array $vars 变量 |
||
129 | * @return mixed |
||
130 | */ |
||
131 | public function invokeMethod($method, $vars=[]) |
||
143 | |||
144 | /** |
||
145 | * 调用反射执行callable 支持参数绑定 |
||
146 | * @access public |
||
147 | * @param mixed $callable |
||
148 | * @param array $vars 变量 |
||
149 | * @return mixed |
||
150 | */ |
||
151 | public function invoke($callable, $vars=[]) |
||
152 | { |
||
153 | if ($callable instanceof \Closure) { |
||
154 | $result=$this->invokeFunction($callable, $vars); |
||
155 | } else { |
||
156 | $result=$this->invokeMethod($callable, $vars); |
||
157 | } |
||
158 | return $result; |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * 调用反射执行类的实例化 支持依赖注入 |
||
163 | * @access public |
||
164 | * @param string $class 类名 |
||
165 | * @param array $vars 变量 |
||
166 | * @return mixed |
||
167 | */ |
||
168 | 1 | public function invokeClass($class, $vars=[]) |
|
169 | { |
||
170 | 1 | $reflect=new \ReflectionClass($class); |
|
171 | 1 | $constructor=$reflect->getConstructor(); |
|
172 | 1 | if ($constructor) { |
|
173 | 1 | $args=$this->bindParams($constructor, $vars); |
|
174 | } else { |
||
175 | $args=[]; |
||
176 | } |
||
177 | 1 | return $reflect->newInstanceArgs($args); |
|
178 | } |
||
179 | |||
180 | /** |
||
181 | * 绑定参数 |
||
182 | * @access protected |
||
183 | * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类 |
||
184 | * @param array $vars 变量 |
||
185 | * @return array |
||
186 | */ |
||
187 | 1 | protected function bindParams($reflect, $vars=[]) |
|
188 | { |
||
189 | 1 | $args=[]; |
|
190 | 1 | if ($reflect->getNumberOfParameters() > 0) { |
|
191 | // 判断数组类型 数字数组时按顺序绑定参数 |
||
192 | 1 | reset($vars); |
|
193 | 1 | $type=key($vars) === 0 ? 1 : 0; |
|
194 | 1 | $params=$reflect->getParameters(); |
|
195 | 1 | foreach ($params as $param) { |
|
196 | 1 | $name=$param->getName(); |
|
197 | 1 | $class=$param->getClass(); |
|
198 | 1 | if ($class) { |
|
199 | $className=$class->getName(); |
||
200 | $args[]=$this->make($className); |
||
201 | 1 | } elseif (1 == $type && !empty($vars)) { |
|
202 | $args[]=array_shift($vars); |
||
203 | 1 | } elseif (0 == $type && isset($vars[$name])) { |
|
204 | $args[]=$vars[$name]; |
||
205 | 1 | } elseif ($param->isDefaultValueAvailable()) { |
|
206 | 1 | $args[]=$param->getDefaultValue(); |
|
207 | } else { |
||
208 | 1 | throw new \InvalidArgumentException('method param miss:'.$name); |
|
209 | } |
||
210 | } |
||
211 | } |
||
212 | 1 | return $args; |
|
213 | } |
||
214 | |||
215 | public function offsetExists($key) |
||
219 | |||
220 | public function offsetGet($key) |
||
224 | |||
225 | public function offsetSet($key, $value) |
||
229 | |||
230 | public function offsetUnset($key) |
||
234 | |||
235 | public function __set($name, $value) |
||
239 | |||
240 | public function __get($name) |
||
244 | |||
245 | public function __isset($name) |
||
249 | |||
250 | public function __unset($name) |
||
254 | |||
255 | } |