I. Service Container Concept
As the Laravel docs describe:
The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.
Translated as:
Laravel service container is a powerful tool for managing class dependencies and implementing dependency injection.
So the question pops up in my head, what is “class dependencies” and “dependency injection”?. It’s a hassle, isn’t it? So I’ll go through “class dependencies” and “dependency injection” first, understanding these concepts will make it a lot easier to understand.
II. Class dependencies
When a Class A uses some function of Class B, it is said that: Class A has a dependency relationship with Class B.
Illustrated code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">class</span> <span class="token class-name-definition class-name">Http</span> <span class="token punctuation">{</span> <span class="token keyword">function</span> <span class="token function-definition function">get</span> <span class="token punctuation">(</span> <span class="token variable">$url</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// todo</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">Class</span> <span class="token class-name-definition class-name">Crawler</span> <span class="token punctuation">{</span> <span class="token keyword">function</span> <span class="token function-definition function">crawl</span> <span class="token punctuation">(</span> <span class="token variable">$url</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$http</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Http</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$res</span> <span class="token operator">=</span> <span class="token variable">$http</span> <span class="token operator">-></span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token variable">$url</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
We see that in the crawl() function of the Crawler class, the get() function of the Http class is used.
III. Dependency injection
Dependency injection(DI) is a programming technique bla bla … if you read it, it will be a bit confusing. We understand simply ntn. DI is a technique that helps us to implement by “injecting” a class that depends on the main class. Regarding injection, we have 3 ways:
1. Constructor Injection
Injection via constructor (function __contstructor)
2. Setter Injection
Inject via setter/gettter . function
3. Interface Injection
Inject through interface
In Php, we often encounter the first case ie Constructor Injection. So our examples will use the constructor injection implementation. Here is an example of pure php code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">Class</span> <span class="token class-name-definition class-name">Http</span> <span class="token punctuation">{</span> <span class="token keyword">function</span> <span class="token function-definition function">get</span> <span class="token punctuation">(</span> <span class="token variable">$url</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token number">1</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-definition class-name">Crawler</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token variable">$http</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</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 property">http</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Http</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">function</span> <span class="token function-definition function">doCraw</span> <span class="token punctuation">(</span> <span class="token variable">$url</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$res</span> <span class="token operator">=</span> <span class="token variable">$this</span> <span class="token operator">-></span> <span class="token property">http</span> <span class="token operator">-></span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token variable">$url</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span> |
As we can see to implement DI we need to do 3 things:
- Declare a property $http
- In the constructor of the Crawler class, we implement injecting the instance of the Http class into the $http . property
- When using Http function in Crawler class, just call $this->http->get()
Here is the code in Laravel:
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 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">namespace</span> <span class="token package">App Http Controllers</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App Http Controllers Controller</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App Repositories UserRepository</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">App Models User</span> <span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token package">Illuminate View View</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name-definition class-name">UserController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span> <span class="token punctuation">{</span> <span class="token comment">/** * Create a new controller instance. */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span> <span class="token punctuation">(</span> <span class="token keyword">protected</span> <span class="token class-name type-declaration">UserRepository</span> <span class="token variable">$users</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">/** * Show the profile for the given user. */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">show</span> <span class="token punctuation">(</span> <span class="token keyword type-hint">string</span> <span class="token variable">$id</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token class-name return-type">View</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 property">users</span> <span class="token operator">-></span> <span class="token function">find</span> <span class="token punctuation">(</span> <span class="token variable">$id</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">view</span> <span class="token punctuation">(</span> <span class="token string single-quoted-string">'user.profile'</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> <span class="token string single-quoted-string">'user'</span> <span class="token operator">=></span> <span class="token variable">$user</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
IV. Back to Service Container
Now that we understand the two concepts of “class dependencies” and “dependency injection”, let’s return to Laravel! Repeat the concept mentioned at the beginning of the article.
Laravel service container is a powerful tool for managing class dependencies and implementing dependency injection.
Explanation: Laravel provides a so-called “Service container” which is very powerful. Soon by code I will show you this powerful tool of laravel. This tool was born for the purpose of implementing DI, that is, it will receive dependent classes and have a way to pull these dependent classes to use. Thus, the Service container is a place to store and deploy dependent classes. Why is it important in the design of Laravel Architecture, because this is where all the classes big and small in Laravel are managed. It is extremely important.
The actual implementation problem in the form of a scenario:
Coder : Hey Laravel, I have a few functions of this class that I want to use in Laravel, do you have a way?
Laravel Architecture : Yes, you, you throw that class into the Service container, let it manage, when you need to use it, it has a method for you to pull out and use.
Coder : Ok man, I get it. So how to implement coding?
Laravel Architecture : Here, read it, easy to understand
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 | <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">use</span> <span class="token package">Illuminate Support Facades Route</span> <span class="token punctuation">;</span> <span class="token comment">/* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */</span> <span class="token keyword">class</span> <span class="token class-name-definition class-name">FirstClass</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">print1</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token string single-quoted-string">'print1'</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-definition function">dodo</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token string single-quoted-string">'baby shark dodo'</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-definition class-name">SecondClass</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">print2</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token string single-quoted-string">'print2'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token class-name static-context">Route</span> <span class="token operator">::</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string single-quoted-string">'/'</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 comment">// 1. khởi tạo 1 service container</span> <span class="token variable">$serviceContainer</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified">Illuminate Container Container</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 2. binding vào service container</span> <span class="token variable">$serviceContainer</span> <span class="token operator">-></span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token string single-quoted-string">'class1'</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 keyword">new</span> <span class="token class-name">FirstClass</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">// 3. lôi instance của class đã đăng ký vào</span> <span class="token variable">$instanceOfClass1</span> <span class="token operator">=</span> <span class="token variable">$serviceContainer</span> <span class="token operator">-></span> <span class="token function">make</span> <span class="token punctuation">(</span> <span class="token string single-quoted-string">'class1'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 4. sử dụng các function của class1</span> <span class="token variable">$instanceOfClass1</span> <span class="token operator">-></span> <span class="token function">print1</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">echo</span> <span class="token string double-quoted-string">"<br>"</span> <span class="token punctuation">;</span> <span class="token variable">$instanceOfClass1</span> <span class="token operator">-></span> <span class="token function">dodo</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 operator">-></span> <span class="token function">name</span> <span class="token punctuation">(</span> <span class="token string single-quoted-string">'top'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> </span> |
A little explanation:
- Create a service container, what you call a powerful tool
- Binding a class FirstClass to the service container and name it “class1”
- Resolve or otherwise pull out the instance of that class
- Using functions of “class1”
And this is the result
1 2 3 | print1 baby shark dodo |
At this point, everyone understands what a Service container is, what it is used for and how to use it. In the next post, I will talk a little more about how to use Service containers for standards and what types of binding!