Laravel Practice: Service Providers

Keywords: PHP Laravel github

Preface

The last blog article collected information about Laravel Service Container. Portal We know that service containers have two important functions: binding and parsing. So Laravel is such a multi-functional framework. We may need to introduce some other functional packages in our project. These binding must have a unified management tool and be bound in one place, which is the service provider.

About service providers

At first Laravel was confused by the names of service container and service provider, but now I understand that container is the bottom bucket. We need a lot of materials to fill it, and the provider is some pipes. We are just filling the container with what we need and the service we need through the provider.

Laravel has a mechanism to define and execute the initial processing of each service. The class that implements the initial processing is called a service provider.

In laravel, a service provider is actually a factory class. Its greatest function is to perform service binding. When we need to bind one or more services, we can customize a service provider and then put the logic of service binding into the implementation of this class. In larave, it's easy to customize a service provider by inheriting the IlluminateSupportService Provider class. Here are some key points of a service provider illustrated by a simple custom service provider:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class yourServiceProvider extends ServiceProvider
{
    protected $defer = true;

    public function boot()
    {
        //
    }

    public function register()
    {
        $this->app->singleton('service1', function(){
            return 'service1';
        });
        $this->app->singleton('service2', function(){
            return 'service2';
        });
        $this->app->singleton('service3', function(){
            return 'service3';
        });
    }

    public  function provides()
    {
        return ['service1','service2','service3'];
    }
}

For the service provider class, it can be created by the artisan command:

artisan make:provider yourServiceProvider

The created files are stored in the appProviders directory

Our services are now bound to register() in the yourService Provider class. Although the creation and binding of service providers have been completed, the framework now does not know that there is an additional service provider, so the registe() method in this class will not be invoked during the running of the program, so it needs to be registered somewhere to tell the newly created service providers of the framework, the configuration file config/app.php.

    'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        ...
        ...
        ...
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

    ],

When laravel finds the service provider's class, it initializes the service provider class, obtains a service provider's object, and then calls its register method. Naturally, all the service binding codes in it will execute:

public function registerConfiguredProviders()
    {
        $manifestPath = $this->getCachedServicesPath();

        (new ProviderRepository($this, new Filesystem, $manifestPath))
                    ->load($this->config['app.providers']);
    }

laravel will register all custom service providers. This registration process is actually the process of instantiating the class of the service provider mentioned earlier and calling the register method.

In addition to the register method, there is a boot method in the service provider. This boot method will not be executed until all the service providers have registered. So when you want to parse other services through the container and do some initialization work after the service binding is completed, you can write these logic in the boot method. Because all service providers have been registered by the time the boot method is executed, the boot method ensures that other services can be resolved.

_The above mainly introduces the role and specific use of the laravel service provider. In our usual development, the introduction of third-party packages is such a step (for example, overtrue/laravel-wechat):

  • Installation introduction: composer require "overtrue/laravel-wechat:~4.0"
  • Register Service Provider and Facade in config/app.php (Laravel 5.5 does not require manual registration)
'providers' => [
    // ...
    Overtrue\LaravelWeChat\ServiceProvider::class,
],
'aliases' => [
    // ...
    'EasyWeChat' => Overtrue\LaravelWeChat\Facade::class,
],
  • create profile
artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider

The service provider also has a small problem value to note, because PHP is a basic language, when processing requests, all PHPs are executed from the entry file. For performance reasons, laravel caches all service providers into bootstrap/cache/services.php files at the first initialization, so sometimes when you change a service provider's code, refresh does not necessarily see the desired effect, which may be due to caching. By deleting services. php, you can see the effect you want.

Once again, I feel that Zhuge's article, after reading, received a large amount of goods. The content of this article is relatively rough. If you want to know more about it, you can see here. Some Key Points of Container Management in laravel Framework

Posted by kraadde on Mon, 21 Jan 2019 08:24:13 -0800