Home >PHP Framework >Laravel >An introduction to the advantages of using Laravel service containers

An introduction to the advantages of using Laravel service containers

藏色散人
藏色散人forward
2020-03-19 08:58:002816browse

If you say what is the core of the laravel framework, then it is undoubtedly the service container. Understanding the concept of service containers is very important for us to use laravel. It should be said that understanding the concept of service containers is an important condition for distinguishing whether to get started with laravel. Because the entire framework is built on the basis of service containers.

Recommendation: laravel tutorial

An introduction to the advantages of using Laravel service containers

laravel service container is like a highly automated factory, you need to customize the model , manufactured using specific interfaces.

Because the service container is used, the instantiation method of most objects in laravel is like this:

$obj1 = $container->make('class1', 'class2');
$obj2 = $container->make('class3', 'class4');

But without using the service container, the following method can also be done ::

$obj1 = new class1(new class2());
$obj2 = new class3(new class4());

So what are the advantages of using service containers? Let's analyze its advantages through some specific examples:

Example 1, sending emails

We encapsulate the function of sending emails into a class, which needs to be used time, instantiate and call the send method.

The following are common ways not to use laravel service container:

/**
 *发送邮件服务类
 */
class EmailService{
    public function send(){
        //todo 发送邮件方法
    }
}
//如果任何地方要发邮件我们就复制下面这两行代码
$emailService = new EmailService();
$emailService->send();

After using laravel service container:

$this->app->bind('emailService', function ($app) {
    return new EmailService();
});
//如果任何地方要发邮件我们就复制下面这两行代码
$emailService = app('emailService');
$emailService->send();

This makes our code more concise, and because With the middle layer, the flexibility is improved (decoupling), so whether it is testing (we can fake the class to replace the EmailService class during testing) or optimizing the EmailService class, it becomes more convenient.

//只需要改这一个地方
$this->app->bind('emailService', function ($app) {
    return new SupperEmailService();
});

We don’t need to touch the other calling parts at all. If we don’t have this binding operation, we have to make changes in every place where the mail service is used.

//使用到EamilSerice类的每个地方都要更改
$emailService = new SupperEmailService();
$emailService->send();

Example 2, Implementing singleton mode

Still the above example, for performance reasons, you need the SupperEamilService class to implement singleton mode, so if you do not use In the case of laravel service container, you change the SupperEmailService class as follows:

class SupperEamilService{
      //创建静态私有的变量保存该类对象
     static private $instance;
   
      //防止直接创建对象
      private function __construct(){
         
     }
         //防止克隆对象
     private function __clone(){
 
     }
     static public function getInstance(){
                 //判断$instance是否是Uni的对象
                 //没有则创建
         if (!self::$instance instanceof self) {
             self::$instance = new self();
         }
         return self::$instance;
         
     }
     
     //发送邮件方法
     public function send(){
        
     }
 }

In addition, since the SupperEamilService class constructor is now private, the object cannot be instantiated through the new keyword, so in each instance The SupperEmailService class must be changed to this:

$emailService=SupperEmailService::getInstance();
$emailService->send();

The laravel service container naturally supports singletons. The following is how laravel implements it:

//只需要把bind改成singleton 
$this->app->singleton('emailService', function ($app) {
    return new SupperEmailService();
});

To implement a singleton, you only need to change one line of code. , change the original bind method to singleton, and the singleton taken out through the container is really convenient.

Example 3, Traveler Goes Travel

This example assumes that a traveler goes to Tibet. He can take the train (train) or walk (leg).

Do not use laravel service container:

<?php
interface TrafficTool
{
  public function go();
}
class Train implements TrafficTool
{
  public function go()
  {
  echo "train....";
  }
}
class Leg implements TrafficTool
{
  public function go()
  {
  echo "leg..";
  }
}
class Traveller
{
  /**
  * @var Leg|null|Train
  * 旅行工具
  */
  protected $_trafficTool;
  public function __construct(TrafficTool $trafficTool)
  {
  $this->_trafficTool = $trafficTool;
  }
  public function visitTibet()
  {
  $this->_trafficTool->go();
  }
}

When travelers want to travel by train, we usually write like this:

<?php
 $train = new Train();
$tra = new Traveller($train);
$tra->visitTibet();

In fact, this way of writing is already very good, because The dependence on travel tools has been transferred to the outside through interfaces. However, dependencies will still occur when using new to instantiate objects. For example, trafficTool above), which means that we must have a $trafficTool before creating a Traveller, that is, Traveler depends on trafficTool. When using new to instantiate Traveller, There is a coupling between Traveller and trafficTool. In this way, these two components cannot be separated.

Now let’s take a look at how to implement it using the laravel service container:

Bind classes in the service container

<?php
namespace App\Providers;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
  public function register()
  {
     //在服务容器中绑定类
     $this->app->bind( &#39;TrafficTool&#39;, &#39;Train&#39;);
     $this->app->bind(&#39;Traveller&#39;, &#39;Traveller&#39;);
  }
}

Instantiate objects

<?php
// 实例化对象
$tra = app()->make(&#39;Traveller&#39;);
$tra->visitTibet();

When we use the service container to obtain an object of the travel class, the container will automatically inject the parameters required by the object. Before that, I only needed to bind specific classes. This reflected true automation and completely decoupled the travel class and travel tool class. When we need to change the way we travel, we just need to change the binding.

Summary

A few simple examples are given above. If you can fully understand and master the laravel service container, it will provide you with more convenience in actual development. . Of course, it is not perfect, and I will describe its shortcomings in the next blog. In short, the key is to maximize strengths and avoid weaknesses in actual use.

The above is the detailed content of An introduction to the advantages of using Laravel service containers. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete