You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: book/dependencies.md
+74-3Lines changed: 74 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,11 +25,80 @@ it doesn't care how these dependencies are satisfied.
25
25
26
26
You can't eliminate dependencies altogether but you can make them more flexible.
27
27
28
-
## Inversion of control
29
-
30
-
31
28
## Dependency injection
32
29
30
+
There are two ways of re-using things in OOP: inheritance and composition.
31
+
32
+
Inheritance is simple:
33
+
34
+
```php
35
+
class Cache
36
+
{
37
+
public function getCachedValue($key)
38
+
{
39
+
// ..
40
+
}
41
+
}
42
+
43
+
class CachedWidget extends Cache
44
+
{
45
+
public function render()
46
+
{
47
+
$output = parent::getCachedValue('cachedWidget');
48
+
if ($output !== null) {
49
+
return $output;
50
+
}
51
+
// ...
52
+
}
53
+
}
54
+
```
55
+
56
+
The issue here is that these two are becoming unnecessarily coupled or inter-dependent making them more fragile.
57
+
58
+
Another way to handle it is composition:
59
+
60
+
```php
61
+
interface CacheInterface
62
+
{
63
+
public function getCachedValue($key);
64
+
}
65
+
66
+
class Cache implements CacheInterface
67
+
{
68
+
public function getCachedValue($key)
69
+
{
70
+
// ..
71
+
}
72
+
}
73
+
74
+
class CachedWidget
75
+
{
76
+
private $cache;
77
+
78
+
public function __construct(CacheInterface $cache)
79
+
{
80
+
$this->cache = $cache;
81
+
}
82
+
83
+
public function render()
84
+
{
85
+
$output = $this->cache('cachedWidget');
86
+
if ($output !== null) {
87
+
return $output;
88
+
}
89
+
// ...
90
+
}
91
+
}
92
+
```
93
+
94
+
In the above we've avoided unnecessary inheritance and used interface to reduce coupling. You can replace cache implementation without changing `CachedWidget` so it's becoming more stable.
95
+
96
+
The process of getting an instance of `CacheInterface` into `CachedWidget` is called dependency injection. There are multiple ways to do so:
97
+
98
+
- Constructor. Preferred for mandatory dependencies.
99
+
- Setter. OK for optional dependencies.
100
+
- Property. Potentially violates encapsulation.
101
+
33
102
## Dependency container
34
103
35
104
Injecting basic dependencies is simple and easy. You're choosing a place where you don't care about dependencies, which is usually controller which you aren't going to unit-test ever, create instances of dependencies needed and pass these to dependent classes.
@@ -45,3 +114,5 @@ Additionally, lots of dependencies, such as certain third party API wrapper, are
45
114
That's what dependency containers are for.
46
115
47
116
See [official guide](http://www.yiiframework.com/doc-2.0/guide-concept-di-container.html) for more information about Yii's dependency container.
0 commit comments