Laravel Service Provider

介绍

Service Provider是整个Laravel应用程序引导的中心。我们自己的应用程序以及Laravel的所有核心服务都通过Service Provider来引导。

但是,“引导”是什么意思?通常,我们的意思是注册内容,包括注册服务容器绑定,event listener,中间件,甚至路由。Service Provider是配置我们的应用程序的核心。

如果打开config/app.php的文件,则会看到一个providers数组。这些都是为我们的应用程序加载的所有Service Provider类。请注意,其中许多是“deferred”的providers,这意味着它们不会在每个请求上都加载,而仅在实际需要它们提供的服务时才加载。

在本节内容中,我们将学习如何编写自己的Service Provider并将其注册到Laravel应用程序中。


编写Service Provider

所有Service Provider都继承自Illuminate\Support\ServiceProvider类。大多数Service Provider都包含registerboot两个方法。在register方法内,我们应仅将类绑定到服务容器中。绝对不要尝试在该register方法中注册任何事件监听器,路由或任何其他功能。

Artisan CLI可以通过make:provider命令生成新的 provider:

$ php artisan make:provider RiakServiceProvider

register 方法

如前所述,在register方法内,绝对不要尝试在该register方法中注册任何事件监听器,路由或任何其他功能。否则,可能会意外使用尚未加载的Service Provider提供的服务。

让我们看一下基本的Service Provider。在任何Service Provider的方法中,我们始终可以访问$app属性,该属性提供对服务容器的访问:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Riak\Connection;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }
}

上面示例中的Service Provider仅定义一个register方法,并使用该方法定义Riak\Connection的实现,并将二者在服务容器中进行绑定。如果不了解服务容器的工作原理,请查看 Service Container文档

bindingssingletons属性

如果Service Provider注册了许多简单的绑定,则我们可能希望使用bindingssingletons属性,而不是手动注册对每个类在容器中进行绑定。框架加载Service Provider后,它将自动检查以下属性并注册其绑定:

<?php

namespace App\Providers;

use App\Contracts\DowntimeNotifier;
use App\Contracts\ServerProvider;
use App\Services\DigitalOceanServerProvider;
use App\Services\PingdomDowntimeNotifier;
use App\Services\ServerToolsProvider;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * All of the container bindings that should be registered.
     *
     * @var array
     */
    public $bindings = [
        ServerProvider::class => DigitalOceanServerProvider::class,
    ];

    /**
     * All of the container singletons that should be registered.
     *
     * @var array
     */
    public $singletons = [
        DowntimeNotifier::class => PingdomDowntimeNotifier::class,
        ServerProvider::class => ServerToolsProvider::class,
    ];
}

boot 方法

如果我们需要在我们的Service Provider中注册view composer该怎么办?这应该在boot方法内完成。在注册了所有其他Service Provider之后,将调用boot方法,这意味着我们可以访问框架已注册的所有其他服务:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        view()->composer('view', function () {
            //
        });
    }
}

boot 方法依赖注入

您可以在Service Provider的boot方法中键入类型提示。服务容器将自动注入你需要的任何依赖关系:

use Illuminate\Contracts\Routing\ResponseFactory;

public function boot(ResponseFactory $response)
{
    $response->macro('caps', function ($value) {
        //
    });
}

注册 Providers

所有Service Provider都需要在config/app.php配置文件中注册。该文件包含一个providers数组,我们可以在其中列出Service Provider的类名。默认情况下,此数组中列出了一组Laravel自带的核心Service Provider。这些Provider程序是Laravel的核心组件,例如邮件程序,队列,缓存和其他组件。

要注册我们自己的的Provider程序,需要将其添加到数组中:

'providers' => [
    // Other Service Providers

    App\Providers\ComposerServiceProvider::class,
],

延时 Provider

如果我们的 provider 仅在服务容器中注册绑定,则可以选择将其注册为一个延迟的provider,只有在实际需要的时候菜进行绑定。延迟此类 provider 程序的加载可以提高应用程序的性能,因为并不是在每次请求时都需要从文件系统中加载该 provider 程序。

Laravel编译并存储由延迟 Service Provider 提供的所有服务的列表,以及其 Service Provider 类的名称。然后,只有当我们尝试解析这些服务时,Laravel才会加载服务Service Provider

要延迟 provider 的加载,需要实现\Illuminate\Contracts\Support\DeferrableProvider接口并定义provides方法。provides方法应该返回由 provider 注册的服务容器绑定:

<?php

namespace App\Providers;

use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use Riak\Connection;

class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection($app['config']['riak']);
        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [Connection::class];
    }
}

查看笔记

扫码一下
查看教程更方便