架構 ―― 服務提供者

2018-02-24 15:38 更新

架構 —— 服務提供者

1、簡介

服務提供者應用啟動的中心,你自己的應用以及所有Laravel的核心服務都是通過服務提供者啟動。

但是,我們所謂的”啟動“指的是什么?通常,這意味著注冊事物,包括注冊服務容器綁定、時間監(jiān)聽器、中間件甚至路由。服務提供者是應用配置的中心。

如果你打開Laravel自帶的config/app.php文件,將會看到一個providers數組,這里就是應用所要加載的所有服務提供者類,當然,其中很多是延遲加載的,也就是說不是每次請求都會被加載,只有真的用到它們的時候才會加載。

本章里你將會學習如何編寫自己的服務提供者并在Laravel應用中注冊它們。

2、編寫服務提供者

所有的服務提供者繼承自Illuminate\Support\ServiceProvider類。繼承該抽象類要求至少在服務提供者中定義一個方法:register。在register方法內,你唯一要做的事情就是綁事物到服務容器,不要嘗試在其中注冊任何時間監(jiān)聽器,路由或者任何其它功能。

通過Artisan命令make:provider可以簡單生成一個新的提供者:

php artisan make:provider RiakServiceProvider

2.1 register方法

正如前面所提到的,在register方法中只綁定事物到服務容器,而不要做其他事情,否則話,一不小心就能用到一個尚未被加載的服務提供者提供的服務。

現在讓我們來看看一個基本的服務提供者長什么樣:

<?php

namespace App\Providers;

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

class RiakServiceProvider extends ServiceProvider{
    /**
     * 在容器中注冊綁定.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('Riak\Contracts\Connection', function ($app) {
            return new Connection(config('riak'));
        });
    }
}

該服務提供者只定義了一個register方法,并使用該方法在服務容器中定義了一個Riak\Contracts\Connection的實現。如果你不太理解服務容器是怎么工作的,查看其文檔。

2.2 boot方法

如果我們想要在服務提供者中注冊視圖composer該怎么做?這就要用到boot方法了。該方法在所有服務提供者被注冊以后才會被調用,這就是說我們可以在其中訪問框架已注冊的所有其它服務:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class EventServiceProvider extends ServiceProvider{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        view()->composer('view', function () {
            //
        });
    }

    /**
     * 在容器中注冊綁定.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

2.2.1 boot方法的依賴注入

我們可以在boot方法中類型提示依賴,服務容器會自動注冊你所需要的依賴:

use Illuminate\Contracts\Routing\ResponseFactory;

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

3、注冊服務提供者

所有服務提供者都是通過配置文件config/app.php中進行注冊,該文件包含了一個列出所有服務提供者名字的providers數組,默認情況下,其中列出了所有核心服務提供者,這些服務提供者啟動Laravel核心組件,比如郵件、隊列、緩存等等。

要注冊你自己的服務提供者,只需要將其追加到該數組中即可:

'providers' => [
     // 其它服務提供者
     App\Providers\AppServiceProvider::class,
],

4、延遲加載服務提供者

如果你的提供者僅僅只是在服務容器中注冊綁定,你可以選在延遲加載該綁定直到注冊綁定真的需要時再加載,延遲加載這樣的一個提供者將會提升應用的性能,因為它不會在每次請求時都從文件系統(tǒng)加載。

想要延遲加載一個提供者,設置defer屬性為true并定義一個provides方法,該方法返回該提供者注冊的服務容器綁定:

<?php

namespace App\Providers;

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

class RiakServiceProvider extends ServiceProvider{
    /**
     * 服務提供者加是否延遲加載.
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * 注冊服務提供者
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('Riak\Contracts\Connection', function ($app) {
            return new Connection($app['config']['riak']);
        });
    }

    /**
     * 獲取由提供者提供的服務.
     *
     * @return array
     */
    public function provides()
    {
        return ['Riak\Contracts\Connection'];
    }

}

Laravel編譯并保存所有延遲服務提供者提供的服務及服務提供者的類名。然后,只有當你嘗試解析其中某個服務時Laravel才會加載其服務提供者。

擴展閱讀:實例教程 —— 創(chuàng)建 Service Provider 測試示例

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號