-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdependencyInjection.php
132 lines (104 loc) · 2.46 KB
/
dependencyInjection.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
class Client
{
public function __construct(
private ServiceA $serviceA,
private ServiceB $serviceB
) {
}
public function execute(): string
{
return $this->serviceA->make() . '<br>' . $this->serviceB->build();
}
}
interface ServiceA
{
public function make(): string;
}
class ServiceAImplementation implements ServiceA
{
public function make(): string
{
return __METHOD__;
}
}
interface ServiceB
{
public function build(): string;
}
class ServiceBImplementation implements ServiceB
{
public function build(): string
{
return __METHOD__;
}
}
class Provider
{
private array $bindings = [
ServiceA::class => ServiceAImplementation::class,
ServiceB::class => ServiceBImplementation::class,
];
public function getBindings(): array
{
return $this->bindings;
}
}
class Injector
{
private array $bindings;
private ReflectionClass $reflectionClass;
private array $arguments;
/**
* @throws ReflectionException
*/
public function createObject(string $class): object
{
$this->init($class);
$this->prepareArguments();
return $this->createInstance();
}
/**
* @throws ReflectionException
*/
private function init(string $class): void
{
$provider = new Provider();
$this->bindings = $provider->getBindings();
$this->reflectionClass = new ReflectionClass($class);
}
private function prepareArguments(): void
{
$constructor = $this->reflectionClass->getConstructor();
$params = $constructor->getParameters();
foreach ($params as $param) {
$this->createArgument($param);
}
}
private function createArgument(ReflectionParameter $param): void
{
$interfaceName = $param->getType()->getName();
$className = $this->findClassByInterface($interfaceName);
$this->arguments[] = new $className;
}
private function findClassByInterface($interfaceName): string
{
return $this->bindings[$interfaceName];
}
/**
* @throws ReflectionException
*/
private function createInstance(): object
{
return $this->reflectionClass->newInstanceArgs($this->arguments);
}
}
/**
* Client
*/
$injector = new Injector();
try {
$client = $injector->createObject(Client::class);
echo $client->execute();
} catch (ReflectionException) {
}