Nếu bạn đã làm việc với các Framework như Laravel thì chắc hẳn bạn sẽ biết đến Service Container. Service Container trong Laravel là một Dependency Injection (DI) Container, là nơi quản lý class dependency và thực hiện dependency injection
.
Để sử dụng Service Container thì khá đơn giản tuy nhiên tìm hiểu cách nó được xây dựng như thế nào thì là một vấn đề khác. Trong bài viết này mình sẽ giới thiệu một vài kiến thức mà Laravel áp dụng để xây dựng Service Container, từ đó thử build 1 mini Dependency Injection (DI) Container tương tự Service Container xem sao nhé.
Nội dung bài viết:
- Dependency Injection
- Reflection (QUAN TRỌNG)
- Build mini DI Container
Trong đấy quan trọng nhất là Reflection, đây là vấn đề mấu chốt để xây dựng DI container.
Dependency Injection
Nếu một Class A hoạt động phụ thuộc vào một vài Class khác, thay vì khởi tạo các instance của các Class kia bên trong Class A, ta sẽ inject những instance đó vào thông qua constructor hay setter. Những instance của các Class mà Class A cần để hoạt động đó được gọi là dependency.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$userService</span><span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>UserService <span class="token variable">$userService</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">userService</span> <span class="token operator">=</span> <span class="token variable">$userService</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">register</span><span class="token punctuation">(</span><span class="token variable">$dataUser</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$user</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 property">userService</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">register</span><span class="token punctuation">(</span><span class="token variable">$dataUser</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token single-quoted-string string">'Success'</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token single-quoted-string string">'Fail'</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">class</span> <span class="token class-name">UserService</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$userRepository</span><span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>UserRepositoryInterface <span class="token variable">$userRepository</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">userRepository</span> <span class="token operator">=</span> <span class="token variable">$userRepository</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">register</span><span class="token punctuation">(</span><span class="token variable">$dataUser</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">userRepository</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">store</span><span class="token punctuation">(</span><span class="token variable">$dataUser</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">interface</span> <span class="token class-name">UserRepositoryInterface</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">store</span><span class="token punctuation">(</span><span class="token variable">$data</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">UserRepository</span> <span class="token keyword">implements</span> <span class="token class-name">UserRepositoryInterface</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">store</span><span class="token punctuation">(</span><span class="token variable">$data</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 function">model</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token variable">$data</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Có thể thấy để UserController
hoạt động cần 1 instance UserService
, tương tự để UserService
hoạt động cần 1 instance UserRepositoryInterface
.
Ở đây chúng ta đã áp dụng DI bằng cách inject các class dependency thông qua constructor như ví dụ trên.
Tuy nhiên khi sử dụng UserController
1 2 3 | <span class="token variable">$userController</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserController</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">UserService</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">UserRepository</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$userController</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">register</span><span class="token punctuation">(</span><span class="token variable">$data</span><span class="token punctuation">)</span> |
Sẽ ra sao nếu như class có nhiều dependency, và những dependency này lại có nhiều dependency khác?
Ví dụ như UserService
cần GroupService
, GroupService
cần GroupRepository
:
1 2 | <span class="token variable">$userController</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserController</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">UserService</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">UserRepository</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">GroupService</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">GroupRepository</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Đây chính là lúc bạn cần DI Container để giải quyết vấn đề trên. Sức mạnh của DI Container là ở chỗ, bạn có thể “type-hint” dependency trong constructor hoặc method của class, nó sẽ tự động resolve và inject nó vào class cho bạn. Sử dụng Reflection là cách DI Container làm nên điều kì diệu đấy.
Reflection
Nguyên văn từ PHP:
PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, the reflection API offers ways to retrieve doc comments for functions, classes and methods.
Dịch nôm na: Reflection là khả năng để chương trình “inspect” chính nó, bạn có thể khảo sát class, interface, function, method và cả extension xem nó tên gì, cần gì,… Nó còn có thể lấy được comment của function, class, method.
Mình sẽ giới thiệu với bạn 1 vài build-in function của Reflection sẽ áp dụng vào việc xây dựng DI Container dưới đây, chi tiết hơn bạn có thể vào docs Reflection.
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 | <span class="token variable">$reflector</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReflectionClass</span><span class="token punctuation">(</span><span class="token variable">$concrete</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// check if class is instantiable</span> <span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">isInstantiable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// get class constructor</span> <span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getConstructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// get new instance from class</span> <span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">newInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// get new instance with dependencies resolved</span> <span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">newInstanceArgs</span><span class="token punctuation">(</span><span class="token variable">$dependencies</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// get constructor params</span> <span class="token variable">$constructor</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getParameters</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// get the type hinted class</span> <span class="token variable">$params</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// check if default value for a parameter is available</span> <span class="token variable">$parameter</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">isDefaultValueAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// get default value of parameter</span> <span class="token variable">$parameter</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getDefaultValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Laravel Service Container là một DI Container, về cơ bản thì Laravel sử dụng Reflection kết hợp đệ quy để resolve các dependency từ đấy tạo nên sức mạnh của Service Container mà bạn đã thấy.
Chưa tin thì bạn vào đây https://github.com/laravel/framework/blob/master/src/Illuminate/Container/Container.php
Tại function build (dòng 793)
1 2 3 4 5 6 | <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token variable">$reflector</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReflectionClass</span><span class="token punctuation">(</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 keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ReflectionException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BindingResolutionException</span><span class="token punctuation">(</span><span class="token double-quoted-string string">"Target class [<span class="token interpolation"><span class="token variable">$concrete</span></span>] does not exist."</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token variable">$e</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Chưa biết thế nào nhưng có từ ReflectionClass
thì chắc là đúng rồi?
Build Mini DI Container
Ok giờ đến cách xây dựng DI như thế nào, mời bạn xem source code dưới đây, chi tiết mình đã comment từng function. Có gì không hiểu bạn cứ comment phía dưới nhé.
Mini DI Container
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 | <span class="token keyword">class</span> <span class="token class-name">Container</span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token variable">$instances</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">/** * Đăng ký một class hay interface với Container * * @param $abstract * @param $concrete */</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 keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_null</span><span class="token punctuation">(</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 variable">$concrete</span> <span class="token operator">=</span> <span class="token variable">$abstract</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">instances</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 comment">/** * Lấy ra instance từ Container * * @param $abstract * @return mixed|object * @throws Exception */</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 variable">$parameters</span> <span class="token operator">=</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">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isset</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">instances</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 class="token variable">$this</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 variable">$abstract</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 variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">resolve</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">instances</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">$parameters</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/** * Sử dụng Reflection và đệ quy (hàm resolveDependencies) * để inspect class và lấy các class dependency của nó cho đến hết * * @param $concrete * @return mixed|object * @throws ReflectionException */</span> <span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token variable">$concrete</span><span class="token punctuation">,</span> <span class="token variable">$parameters</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$concrete</span> <span class="token keyword">instanceof</span> <span class="token class-name">Closure</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 variable">$this</span><span class="token punctuation">,</span> <span class="token variable">$parameters</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token variable">$reflector</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReflectionClass</span><span class="token punctuation">(</span><span class="token variable">$concrete</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">isInstantiable</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">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token double-quoted-string string">"Class <span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$concrete</span><span class="token punctuation">}</span></span> is not instantiable"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token variable">$constructor</span> <span class="token operator">=</span> <span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getConstructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_null</span><span class="token punctuation">(</span><span class="token variable">$constructor</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 variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">newInstance</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">$parameters</span> <span class="token operator">=</span> <span class="token variable">$constructor</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getParameters</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$dependencies</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">resolveDependencies</span><span class="token punctuation">(</span><span class="token variable">$parameters</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token variable">$reflector</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">newInstanceArgs</span><span class="token punctuation">(</span><span class="token variable">$dependencies</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/** * Sử dụng Reflection và đệ quy để * inspect class và lấy các class dependency của nó cho đến hết * @param $parameters * @return array * @throws Exception */</span> <span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function">resolveDependencies</span><span class="token punctuation">(</span><span class="token variable">$parameters</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$dependencies</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">foreach</span> <span class="token punctuation">(</span><span class="token variable">$parameters</span> <span class="token keyword">as</span> <span class="token variable">$parameter</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$dependency</span> <span class="token operator">=</span> <span class="token variable">$parameter</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_null</span><span class="token punctuation">(</span><span class="token variable">$dependency</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$parameter</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">isDefaultValueAvailable</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">$dependencies</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$parameter</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getDefaultValue</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">else</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token double-quoted-string string">"Can not resolve dependency <span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$parameter</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">name</span><span class="token punctuation">}</span></span>"</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">else</span> <span class="token punctuation">{</span> <span class="token variable">$dependencies</span><span class="token punctuation">[</span><span class="token punctuation">]</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">make</span><span class="token punctuation">(</span><span class="token variable">$dependency</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">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 keyword">return</span> <span class="token variable">$dependencies</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Chúng ta sẽ thử sử dụng class Container vừa mới xây dựng áp dụng vào ví dụ đầu bài nhé.
1 2 3 4 5 6 7 | <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 punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Bind Interface với class Implementation</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>UserRepositoryInterface<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">,</span> UserRepository<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Resolve instance của UserController</span> <span class="token variable">$userController</span> <span class="token operator">=</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>UserController<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$userController</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">register</span><span class="token punctuation">(</span><span class="token variable">$dataUser</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 'Success' by echo</span> |
Hoặc bạn cũng có thể bind 1 Closure (kèm params)
1 2 3 4 5 6 7 8 | <span class="token comment">// Bind Closure</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>UserRepositoryInterface<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token variable">$container</span><span class="token punctuation">,</span> <span class="token variable">$parameters</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">UserRepository</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 class="token punctuation">;</span> <span class="token comment">// Resolve instance của UserController với array params</span> <span class="token variable">$userController</span> <span class="token operator">=</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>UserController<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</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 class="token variable">$userController</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">register</span><span class="token punctuation">(</span><span class="token variable">$dataUser</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 'Success' by echo</span> |
Trên đây mình đã giới thiệu với bạn cách xây dựng 1 Dependency Injection Container. Hi vọng từ bài viết này bạn có thể hiểu hơn về cách DI Container được xây dựng và hoạt động như thế nào. Nếu có thắc mắc và góp ý bạn comment phía dưới nhé. Cảm ơn bạn ?
Tham khảo:
https://viblo.asia/p/laravel-beauty-tim-hieu-ve-service-container-3KbvZ1wLGmWB
https://viblo.asia/p/dependency-injection-hoat-dong-the-nao-trong-laravel-3Q75wD3JKWb