In this article, we will implement the implementation of IoC Container.
1. Initalize project
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ?phpioccontainer ┣ ?src ┃ ┗ ?Illuminate ┃ ┃ ┣ ?Container ┃ ┃ ┃ ┗ ?Container.php ┃ ┃ ┗ ?Contracts ┃ ┃ ┃ ┗ ?Container ┃ ┃ ┃ ┃ ┗ ?Container.php ┣ ?tests ┃ ┗ ?Container ┃ ┃ ┗ ?ContainerTest.php ┣ ?composer.json ┗ ?index.php |
Above is the directory structure for our project creation. The contents of the files, respectively, will be as follows:
composer.json
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token punctuation">{</span> <span class="token property">"name"</span> <span class="token operator">:</span> <span class="token string">"vscode/phpioccontainer"</span> <span class="token punctuation">,</span> <span class="token property">"autoload"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"psr-4"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"Illuminate\"</span> <span class="token operator">:</span> <span class="token string">"src/Illuminate/"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token property">"require-dev"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"phpunit/phpunit"</span> <span class="token operator">:</span> <span class="token string">"^9"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
src / Illuminate / Container / Container.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">Illuminate Container</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Contracts Container Container</span> <span class="token keyword">as</span> ContainerContract <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">Container</span> <span class="token keyword">implements</span> <span class="token class-name">ContainerContract</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$bindings</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">,</span> <span class="token variable">$concrete</span> <span class="token operator">=</span> <span class="token constant">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token single-quoted-string string">'bind'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">make</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token single-quoted-string string">'make'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
src / Illuminate / Contracts / Container / Container.php
1 2 3 4 5 6 7 8 9 10 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">Illuminate Contracts Container</span> <span class="token punctuation">;</span> <span class="token keyword">interface</span> <span class="token class-name">Container</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">,</span> <span class="token variable">$concrete</span> <span class="token operator">=</span> <span class="token constant">null</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">make</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
tests / Container / ContainerTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">Illuminate Tests Container</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Container Container</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">PHPUnit Framework TestCase</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">ContainerTest</span> <span class="token keyword">extends</span> <span class="token class-name">TestCase</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">testClosureResolution</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$container</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Container</span> <span class="token punctuation">;</span> <span class="token variable">$container</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'name'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token single-quoted-string string">'You'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">assertSame</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'You'</span> <span class="token punctuation">,</span> <span class="token variable">$container</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">make</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'name'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
That is the content of our 4 main files in this post.
If we run the unit test at this point, the test will definitely fail (RED), and this is what we want, in the spirit of TDD .
Our work to do now is to make the test pass (GREEN).
2. Implement Container
2.1. Closure resolution
We’ll implement the simplest form of the container, as it only does resolve closures that are binding. The idea is relatively simple.
bind this with that . make that then give me this
The idea of implement is we will have an array of bindings[]
to store all the bindings.
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 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">Illuminate Container</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate Contracts Container Container</span> <span class="token keyword">as</span> ContainerContract <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">Container</span> <span class="token keyword">implements</span> <span class="token class-name">ContainerContract</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$bindings</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">,</span> <span class="token variable">$concrete</span> <span class="token operator">=</span> <span class="token constant">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">bindings</span> <span class="token punctuation">[</span> <span class="token variable">$abstract</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$concrete</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">make</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$concrete</span> <span class="token operator">=</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">getConcrete</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token variable">$concrete</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function">getConcrete</span> <span class="token punctuation">(</span> <span class="token variable">$abstract</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token variable">$this</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">bindings</span> <span class="token punctuation">[</span> <span class="token variable">$abstract</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
The implementation is quite simple, now let’s try our unit test again
1 2 3 4 5 6 7 8 9 10 | $ ./vendor/bin/phpunit tests PHPUnit 9.5.2 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 00:00.004, Memory: 4.00 MB OK (1 test, 1 assertion) |
Hurray! Passed!
2.1. Singleton
… To Be Continued!
Thank you for reading the article, see you in the next post, we will proceed to implement the singleton form of binding!