介绍

Service Providers 是所有 Laravel 应用启动(Bootstrapping)的中心位置。包括你自己的应用,还有所有 Laravel 的核心服务都是通过 Service Providers 启动的。

启动的大概的意思就是去注册一些东西,包括注册 Service Container,事件监听器,过滤器,甚至是路由。Service Providers 是配置你的应用的中心位置。

打开 Laravel 里的 config/app.php 文件,你会看到一个 providers 数组。这些就是你的应用要加载的所有的 Service provider 类。这里面有些是延迟(deferred)Providers ,意思就是它们不会在每次请求的时候都去加载,只有在真正需要它们提供的服务的时候才会被载入进来。

在下面我们学一下怎么样创建自己的 Service Providers ,并且把它们注册到 Laravel 的应用里。

基本的 Provider 示例

所有的 Service providers 都会继承 Illuminate\Support\ServiceProviders 这个类。这个抽象类要求在你的 Provider 至少要定义一个叫 register 的方法。在这个 register 方法里面,你只能去绑定东西到 Service Container 里面。不能在 register 方法里去干别的事,比如去注册事件监听器,路由,或者是其它的功能。

使用 make:provider 这个 Artisan 命令可以去生成一个 provider :

php artisan make:provider RiakServiceProvider

Register 方法

下面看一个基本的 Service Provider:

<?php namespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider {    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {        $this->app->singleton('Riak\Contracts\Connection', function($app)
        {            return new Connection($app['config']['riak']);
        });
    }

}

上面这个 Service Provider 里面只定义了一个 register 方法,并且使用这个方法在 Service Container 里面定义实施了一个 Riak\Contracts\Connection。后面我们会介绍到什么是 Service Container。

这个类是在 App\Providers 这个命名空间下,这是在 Laravel 里的 Service Providers 的默认的位置。你也可以把它修改成自己想要的。你的 Service Providers 可以放到任何 Composer 能加载到的地方。

Boot 方法

如果想在我们的 Service Provider 里面去注册一个事件监听器,可以用 boot 方法。这个方法会在所有其它的 Serivce Providers 都被注册以后去调用,意思就是你可以使用所有的在框架里注册的 Services 。

<?php namespace App\Providers;use Event;use Illuminate\Support\ServiceProvider;class EventServiceProvider extends ServiceProvider {    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Event::listen('SomeEvent', 'SomeEventHandler');
    }    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {        //    }

}

我们可以为 boot 方法 type-hint 依赖。Service Container 会自动注入任何你需要的依赖:

use Illuminate\Contracts\Events\Dispatcher;public function boot(Dispatcher $events){
    $events->listen('SomeEvent', 'SomeEventHandler');
}

注册 Providers

所有的 Service Providers 都是在 config/app.php 这个配置文件里面注册的。这个文件里面包含了一个叫 providers 的数组,在这里你可以列出你自己的 Service Providers 的名字。默认情况下,这里会列出所有的 Laravel 核心的 Service Providers 。这些 Providers 会启动 Laravel 核心的组件,比如 mailer,queue,cache 等等。

注册你自己的 Providers,可以把它添加到这个数组里:

'providers' => [    // Other Service Providers
    'App\Providers\AppServiceProvider',
],

Deferred Providers

如果你的 Provider 只想在 Service Container 里面注册绑定,你可以选择延迟它的注册,在真正需要用到注册的绑定的时候才去注册它。延迟加载这样的 Provider 可以提升应用的性能,因为它们不会在每次请求的时候都从文件系统上加载进来。

延迟加载一个 Provider,可以把 defer 属性设置成 ture ,再定义一个 provides 方法。这个方法会返回 Provider 注册绑定的 Service Container:

<?php namespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider {    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {        $this->app->singleton('Riak\Contracts\Connection', function($app)
        {            return new Connection($app['config']['riak']);
        });
    }    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {        return ['Riak\Contracts\Connection'];
    }

}

Laravel 会编译并且存储一个列表,就是所有的延迟服务 Providers 提供的服务,包含服务 Provider 类的名字。这样只有在你决定要使用这些服务的时候,Laravel 会去载入 Service Provider 。