Skip to content

Commit 1feed0e

Browse files
committed
re-written
1 parent f938b8a commit 1feed0e

File tree

2 files changed

+127
-87
lines changed

2 files changed

+127
-87
lines changed

README.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ Dependency Injection Container
44

55
## Installation
66

7-
1. Run
7+
1. Run
88
```
99
composer require appzcoder/container:"dev-master"
1010
```
11-
11+
1212
2. Add bellow lines to your script
13-
```php
14-
require 'vendor/autoload.php';
15-
```
13+
```php
14+
require 'vendor/autoload.php';
15+
```
1616
1717
## Usage
1818
@@ -41,35 +41,36 @@ class FooBar { } // No dependencies
4141
4242
4343
// Instantiate the container
44-
$container = Appzcoder\Container\Container::getInstance();
44+
$container = new Appzcoder\Container\Container();
4545
4646
// Registering class with dependencies
47-
$container->make('Foo');
47+
$container->set('Foo');
4848
4949
// Registering class with another name
50-
$container->make('foo', 'Bar');
50+
$container->set('foo', 'Bar');
5151
5252
// Binding a closure object with a name
53-
$container->make('FooBar', function () {
53+
$container->setInstance('FooBar', function () {
5454
return new FooBar();
5555
});
5656
5757
// Registering class with parameters
58-
$container->make('Foo', 'Foo', ['param 1', 'param 2']);
58+
$container->set('Foo', 'Foo', ['param 1', 'param 2']);
5959
6060
// Binding an instance with a name
6161
$instance = new FooBar();
62-
$container->instance('FooBar', $instance);
62+
$container->setInstance('FooBar', $instance);
6363
6464
// Binding an instance/object with container's array
6565
$container['FooBar'] = new FooBar();
6666
6767
// Calling a setter method with dependencies
68-
$instance = $container->make('Foo', 'Foo', ['param 1', 'param 2']);
68+
$container->set('Foo', 'Foo', ['param 1', 'param 2']);
69+
$instance = $container->get('Foo');
6970
$container->call([$instance, 'setterMethod'], ['param 1', 'param 2']);
7071
7172
// Accessing container or getting instances
72-
$instance1 = $container->make('Foo');
73+
$instance1 = $container->get('Foo');
7374
$instance2 = $container['Foo']; // For this should have registered or bounded "Foo"
7475
7576
```

src/Container.php

Lines changed: 113 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44

55
use ArrayAccess;
66
use Closure;
7+
use Exception;
78
use ReflectionClass;
89
use ReflectionFunction;
910
use ReflectionMethod;
1011

1112
class 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

Comments
 (0)