44
55use ArrayAccess ;
66use Closure ;
7+ use Exception ;
78use ReflectionClass ;
89use ReflectionFunction ;
910use ReflectionMethod ;
1011
1112class Container implements ArrayAccess
1213{
13-
1414 /**
15- * Instance of this class .
15+ * Container's definitions .
1616 *
17- * @var static
17+ * @var array
1818 */
19- protected static $ instance ;
19+ protected $ definitions = [] ;
2020
2121 /**
2222 * Container's instances.
@@ -26,104 +26,151 @@ class Container implements ArrayAccess
2626 protected $ instances = [];
2727
2828 /**
29- * Let the container access globally.
29+ * Container's parameters.
30+ *
31+ * @var array
32+ */
33+ protected $ parameters = [];
34+
35+ /**
36+ * Set/Register a class into this container.
37+ *
38+ * @param string $name
39+ * @param string $name (optional)
40+ * @param string $params (optional)
3041 *
31- * @return static
42+ * @return void
3243 */
33- public static function getInstance ( )
44+ public function set ( $ name , $ class = null , $ params = [] )
3445 {
35- if (null === static ::$ instance ) {
36- static ::$ instance = new static ();
46+ if (isset ($ name ) && isset ($ class )) {
47+ if (!class_exists ($ class )) {
48+ throw new Exception ("Your given [ $ class] is not exist. " );
49+ } else {
50+ $ this ->definitions [$ name ] = $ class ;
51+
52+ if (!empty ($ params )) {
53+ $ this ->parameters [$ name ] = $ params ;
54+ }
55+ }
56+ } else {
57+ if (!class_exists ($ name )) {
58+ throw new Exception ("Your given [ $ name] is not exist. " );
59+ } else {
60+ $ this ->definitions [$ name ] = $ name ;
61+ }
3762 }
38-
39- return static ::$ instance ;
4063 }
4164
4265 /**
43- * Register class to create instances based on types .
66+ * Get instance by given a class name or alias name .
4467 *
4568 * @param string $name
46- * @param \Closure|string|object $class
47- * @param array $parameters
48- * @return object
69+ *
70+ * @return object|null
4971 */
50- public function make ($ name, $ class = null , array $ parameters = [] )
72+ public function get ($ name )
5173 {
5274 if (isset ($ this ->instances [$ name ])) {
5375 return $ this ->instances [$ name ];
54- } elseif (isset ($ class ) && is_string ($ class ) && class_exists ($ class )) {
55- return $ this ->instances [$ name ] = $ this ->build ($ class , $ parameters );
56- } elseif (isset ($ class ) && (is_object ($ class ) || $ class instanceof Closure)) {
57- return $ this ->instances [$ name ] = $ class ;
76+ } elseif (isset ($ this ->definitions [$ name ])) {
77+ return $ this ->resolve ($ name );
5878 } else {
59- return $ this -> instances [ $ name ] = $ this -> build ( $ name , $ parameters ) ;
79+ return null ;
6080 }
6181 }
6282
83+ /**
84+ * Resolve or instantiate object of given name.
85+ *
86+ * @param string $name
87+ *
88+ * @return object
89+ */
90+ protected function resolve ($ name )
91+ {
92+ $ class = $ this ->definitions [$ name ];
93+
94+ $ parameters = isset ($ this ->parameters [$ name ]) ? $ this ->parameters [$ name ] : [];
95+
96+ $ reflection = new ReflectionClass ($ class );
97+
98+ if (!$ reflection ->isInstantiable ()) {
99+ throw new Exception ("Your given [ $ class] is not instantiable. " );
100+ }
101+
102+ $ dependencies = $ this ->getDependencies ($ class );
103+ $ instances = [];
104+
105+ foreach ($ dependencies as $ key => $ class ) {
106+ $ offset = is_string ($ key ) ? $ key : $ class ;
107+
108+ if (isset ($ this ->instances [$ offset ])) {
109+ $ instances [$ offset ] = $ this ->instances [$ offset ];
110+ } else {
111+ $ this ->set ($ offset , $ class );
112+
113+ $ instances [$ offset ] = $ this ->get ($ offset );
114+ }
115+ }
116+
117+ $ parameters = array_merge ($ instances , $ parameters );
118+
119+ $ object = $ reflection ->newInstanceArgs ($ parameters );
120+
121+ $ this ->setInstance ($ name , $ object );
122+
123+ return $ object ;
124+ }
125+
63126 /**
64127 * Register an existing instance into this container.
65128 *
66129 * @param string $name
67130 * @param object $instance
68- * @return object
131+ *
132+ * @return void
69133 *
70134 * @throws \Exception
71135 */
72- public function instance ($ name , $ instance )
136+ public function setInstance ($ name , $ instance )
73137 {
74- if (is_object ($ instance )) {
75- return $ this ->instances [$ name ] = $ instance ;
138+ if (is_object ($ instance ) || $ instance instanceof Closure) {
139+ $ this ->instances [$ name ] = $ instance ;
140+ } else {
141+ throw new Exception ("Your given instance is not an object or closure. " );
76142 }
77-
78- throw new \Exception ("Your given instance is not an object. " );
79143 }
80144
81145 /**
82146 * Call a method of an instance and inject its dependencies.
83147 *
84148 * @param array $callback
85149 * @param array $parameters
150+ *
86151 * @return void
87152 */
88153 public function call ($ callback , array $ parameters = [])
89154 {
90155 $ dependencies = $ this ->getMethodDependencies ($ callback );
91- $ instances = $ this ->makeBulk ($ dependencies );
92- $ parameters = array_merge ($ instances , $ parameters );
93-
94- return call_user_func_array ($ callback , $ parameters );
95- }
96156
97- /**
98- * Instantiate object of given class.
99- *
100- * @param string $class
101- * @param array $parameters
102- * @return object
103- *
104- * @throws \Exception
105- */
106- protected function build ($ class , array $ parameters = [])
107- {
108- $ reflection = new ReflectionClass ($ class );
157+ $ instances = [];
158+ foreach ($ dependencies as $ dependency ) {
159+ $ this ->set ($ dependency );
109160
110- if (!$ reflection ->isInstantiable ()) {
111- throw new \Exception ("Your given [ $ class] is not instantiable. " );
161+ $ instances [$ dependency ] = $ this ->resolve ($ dependency );
112162 }
113163
114- $ dependencies = $ this ->getDependencies ($ class );
115- $ instances = $ this ->makeBulk ($ dependencies );
116164 $ parameters = array_merge ($ instances , $ parameters );
117165
118- $ object = $ reflection ->newInstanceArgs ($ parameters );
119-
120- return $ object ;
166+ return call_user_func_array ($ callback , $ parameters );
121167 }
122168
123169 /**
124170 * Get all constructor's dependencies by given class.
125171 *
126172 * @param string $class
173+ *
127174 * @return array
128175 */
129176 protected function getDependencies ($ class )
@@ -148,6 +195,7 @@ protected function getDependencies($class)
148195 * Get all dependencies of a given method.
149196 *
150197 * @param callable|array $callback
198+ *
151199 * @return array
152200 */
153201 protected function getMethodDependencies ($ callback )
@@ -172,74 +220,65 @@ protected function getMethodDependencies($callback)
172220 }
173221
174222 /**
175- * Make bulk instances of given array of classes.
176- *
177- * @param array $classes
178- * @return array
179- */
180- public function makeBulk (array $ classes )
181- {
182- $ instances = [];
183- foreach ($ classes as $ key => $ class ) {
184- $ offset = is_string ($ key ) ? $ key : $ class ;
185- $ instances [$ offset ] = $ this ->make ($ offset , $ class );
186- }
187-
188- return $ instances ;
189- }
190-
191- /**
192- * Clear all registered instances or classes.
223+ * Clear the container.
193224 *
194225 * @return void
195226 */
196227 public function clear ()
197228 {
229+ $ this ->definitions = [];
198230 $ this ->instances = [];
231+ $ this ->parameters = [];
199232 }
200233
201234 /**
202235 * Determine if a given offset exists.
203236 *
204237 * @param string $key
238+ *
205239 * @return boolean
206240 */
207241 public function offsetExists ($ key )
208242 {
209- return isset ($ this ->instances [$ key ]);
243+ return ( isset ($ this ->definitions [ $ key ]) || isset ( $ this -> instances [$ key ]) );
210244 }
211245
212246 /**
213- * Get the value at a given offset.
247+ * Get the value by given a offset.
214248 *
215249 * @param string $key
250+ *
216251 * @return object
217252 */
218253 public function offsetGet ($ key )
219254 {
220- return isset ( $ this ->instances [ $ key]) ? $ this -> instances [ $ key ] : null ;
255+ return $ this ->get ( $ key) ;
221256 }
222257
223258 /**
224- * Set the value at a given offset.
259+ * Set the value by given a offset.
225260 *
226261 * @param string $key
227262 * @param string $value
263+ *
228264 * @return object
229265 */
230266 public function offsetSet ($ key , $ value )
231267 {
232- return $ this ->make ($ key , $ value );
268+ return $ this ->setInstance ($ key , $ value );
233269 }
234270
235271 /**
236272 * Unset the value at a given offset.
237273 *
238274 * @param string $key
275+ *
239276 * @return object
240277 */
241278 public function offsetUnset ($ key )
242279 {
280+ unset($ this ->definitions [$ key ]);
243281 unset($ this ->instances [$ key ]);
282+ unset($ this ->parameters [$ key ]);
244283 }
245284}
0 commit comments