Service Containers in Laravel
- Tram Ho
1. Inversion of Control
In the previous article, I mentioned the SOLID principle and the last principle in SOLID is Dependency Inversion:
- High-level modules should not depend on low-level modules. Both should depend on abstraction
- Interface (abstraction) should not depend on details, but vice versa. (Classes communicate through interfaces, not implementations.)
If Dependency Inversion is not applied, high-level modules depend on low-level modules. When low-level modules change, high-level modules have to change too, which can lead to such mass changes that make maintenance difficult.
Inversion of Control is a design pattern created so that the code adheres to the Dependency Inversion principle. There are several models used to implement Inversion of Control implementation, including: Service Locator, Event, Dependency Injection.
2. Dependency Injection
Dependency Injection is a way to implement the Inversion of Control Pattern. Low-level modules will be injected into high-level modules.
There are three types of Dependency Injection:
Constructer Injection: The dependencies will be passed into a class by the container through the constructor of that class.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">class</span> <span class="token class-name-definition class-name">A</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token variable">$b</span><span class="token punctuation">;</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 class-name type-declaration">B</span> <span class="token variable">$b</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">b</span> <span class="token operator">=</span> <span class="token variable">$b</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token variable">$a</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Setter Injection: Dependencies will be passed into a class through Setter functions.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">class</span> <span class="token class-name-definition class-name">A</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token variable">$b</span><span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">setB</span><span class="token punctuation">(</span><span class="token class-name type-declaration">B</span> <span class="token variable">$b</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">b</span> <span class="token operator">=</span> <span class="token variable">$b</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Interface Injection: The class to inject will implement an interface. This interface contains a function named Inject. Container will inject dependency into a class through calling the Inject function of that interface.
Advantages of DI
- Reduce the connection between modules
- Code easy to maintain, easy to use, replace module
- Easy for writing tests
Disadvantages of DI
- The concept of DI is quite confusing for beginners.
- Make the code more complex and difficult to understand
- Objects are fully initialized from the start, which can reduce performance.
3. Service Container
Starting in the laravel version, there is a service container that replaces the inversion of control container. Service containers are used to manage dependencies and perform dependency injection.
Binding
Almost all of our Service Container bindings will be registered in the Service Provider. Inside a Service Provider we always have access to the Container through $this->app.
Simple Binding
1 2 3 4 | <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hello'</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 string single-quoted-string">'Hello'</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Binding A Singleton
The instance will only be resolved once, subsequent calls will not create a new instance, but only return the previously resolved instance.
Instance Binding
We have an existing instance and we bind it to the Service Container. Each time we take it out we will get back that exact instance.
1 2 3 4 | <span class="token variable">$api</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified"><span class="token punctuation">\</span>Hello<span class="token punctuation">\</span>API</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">HttpClient</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">app</span><span class="token operator">-></span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Hello\API'</span><span class="token punctuation">,</span> <span class="token variable">$api</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Resolve
You can use the make method to get an instance out of the container. The make method receives the class name or interface name you want to resolve.
1 2 | <span class="token variable">$api</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">make</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
If you can’t use variable $app
then you can use the helper function resolve
to get the instance.
1 2 | <span class="token variable">$api</span> <span class="token operator">=</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Through the above process, we can summarize that Service Container is the place to register and manage dependencies.
4. Conclusion
Thank you for following the article, hope the article brings you useful knowledge. See you in the next posts.