About the advantages of using the Laravel service container

If the core of the laravel framework is anything, it is undoubtedly a service container. Understanding the concept of service container is very important for us to use laravel. It should be said that understanding the concept of service container is an important condition to distinguish whether to start laravel. Because the whole framework is built on the basis of service container.

 

The laravel service container is like a highly automated factory. You need to customize the model and use specific interfaces to make it.

Because service containers are used, most of the objects in laravel are instantiated in this way:

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

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

  

But without using the service container, you can do the same in the following ways:

$obj1 = new class1(new class2());

$obj2 = new class3(new class4());

  

So what are the advantages of using service containers? Here are some specific examples to analyze its advantages:

Send email

We encapsulate the function of sending e-mail into a class. When we need to use it, we instantiate and call the sending method.

The following are common ways to avoid using the laravel service container:

/**

 *Send mail service class

 */

class EmailService{

    public function send(){

        //todo sending email method

    }

}

//If you want to email anywhere, we'll copy these two lines of code

$emailService = new EmailService();

$emailService->send();

  

After using the laravel service container:

$this->app->bind('emailService', function ($app) {

    return new EmailService();

});

//If you want to email anywhere, we'll copy these two lines of code

$emailService = app('emailService');

$emailService->send();

  

This makes our code more concise, and because of the middle layer, the flexibility is improved (decoupling), so it is more convenient to test (when testing, we can fake classes to replace EmailService classes) or optimize EmailService classes.

//It's just a place to change

$this->app->bind('emailService', function ($app) {

    return new SupperEmailService();

});

  

We don't need to move the other calls at all. If we don't have this binding operation, we have to make changes in every place where we use the mail service.

//Change everywhere you use the eamilservice class

$emailService = new SupperEmailService();

$emailService->send();

  

Example 2. Implementation of single example mode

In the above example, for performance reasons, you need the suppleemilservice class to implement the singleton mode, so without using the laravel service container, you can change the suppleemailservice class as follows:

class SupperEamilService{

      //Create a static private variable to hold the class object

     static private $instance;

    

      //Prevent objects from being created directly

      private function __construct(){

          

     }

         //Prevent cloning objects

     private function __clone(){

  

     }

     static public function getInstance(){

                 //Determine whether $instance is an object of Uni

                 //Create if not

         if (!self::$instance instanceof self) {

             self::$instance = new self();

         }

         return self::$instance;

          

     }

      

     //Send mail method

     public function send(){

         

     }

 }

  

In addition, since the constructors of the suppleemilservice class are now private, it is not possible to instantiate the object through the new keyword, so every place where the suppleemailservice class is instantiated should be changed to this way:

$emailService=SupperEmailService::getInstance();

$emailService->send();

  

The laravel service container naturally supports a single instance. The following is the implementation of laravel:

//Just change bind to singleton 

$this->app->singleton('emailService', function ($app) {

    return new SupperEmailService();

});

  

To implement a single instance, you need to change even one line of code, change the original bind method to singleton, and the single instance will be taken out through the container, which is very convenient.

The traveller goes on a journey

This example assumes that a traveler can travel to Tibet by train or on foot.

Do not use the 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

  * facilities for travel

  */

  protected $_trafficTool;

  public function __construct(TrafficTool $trafficTool)

  {

  $this->_trafficTool = $trafficTool;

  }

  public function visitTibet()

  {

  $this->_trafficTool->go();

  }

}

  

When a traveler wants to travel by train, we usually write as follows:

<?php

 $train = new Train();

$tra = new Traveller($train);

$tra->visitTibet();

  

In fact, this writing method is very good, because the dependence on travel tools has been transferred to the outside through the way of interface. But when we use new to instantiate objects, we still have dependencies. For example, the above trafficTool). This means that we must have a $trafficTool before creating a Traveller, that is, Traveller depends on trafficTool. When we use new to instantiate Traveller, there is coupling between Traveller and trafficTool. In this way, the two components cannot be separated.

Now let's see how to use the laravel service container:

Binding a class in a service container

<?php

namespace App\Providers;

use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider

{

  public function register()

  {

     //Binding a class in a service container

     $this->app->bind( 'TrafficTool', 'Train');

     $this->app->bind('Traveller', 'Traveller');

  }

}

  

Instanced object
<?php

// Instanced object

$tra = app()->make('Traveller');

$tra->visitTibet();

  

When we use the service container to get the object of the travel class, the container will automatically inject the parameters required by the object. Before that, I just need to bind a specific class, which embodies the real automation and completely decouples the travel class and the travel tool class. When we need to change the way we travel, we just need to change the binding.

summary

Here are a few simple examples. If you can fully understand and master the laravel service container, it will provide you more convenience in actual development. Of course, it is not perfect. In a word, the key is to develop the advantages and avoid the disadvantages in practical use.

 

For more information, please visit

How to become an architect from a coder must see the knowledge point: Catalog Daquan (continuous update) 50W annual salary challenge!

Tags: PHP Laravel

Posted on Thu, 19 Mar 2020 04:45:21 -0400 by NArc0t1c