服務(wù)提供者是所有 Laravel 應(yīng)用程序的啟動中心。你的應(yīng)用程序,以及所有 Laravel 的核心服務(wù),都是透過服務(wù)提供者啟動。
但我們所說的「啟動」指的是什么?一般而言,我們指注冊事物,包括注冊服務(wù)容器綁定、事件監(jiān)聽器、過濾器,甚至路由。服務(wù)提供者是你的應(yīng)用程序配置中心所在。
如果你打開包含于 Laravel 中的 config/app.php
這一文件,你會看到 providers
數(shù)組。這些是所有將加載至你的應(yīng)用程序里的服務(wù)提供者類。當(dāng)然,它們之中有很多屬于「緩載」提供者,意思是除非真正需要它們所提供的服務(wù),否則它們并不會在每一個請求中都被加載。
在這份概述中,你會學(xué)到如何編寫你自己的服務(wù)提供者,并將它們注冊于你的 Laravel 應(yīng)用程序。
所有的服務(wù)提供者都應(yīng)繼承 Illuminate\Support\ServiceProvider
此一類。在這個抽象類中,至少必須定義一個方法: register
。在 register
方法中,應(yīng)該只綁定服務(wù)到服務(wù)容器之中。你永遠不該試圖在 register
方法中注冊任何事件監(jiān)聽器、路由或任何其他功能。
Artisan 命令行接口可以很容易地通過 make:provider
產(chǎn)生新的提供者:
php artisan make:provider RiakServiceProvider
現(xiàn)在,讓我們來看看基本的服務(wù)提供者:
<?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($app['config']['riak']);
});
}
}
這個服務(wù)提供者只定義了一個 register
方法,并在服務(wù)容器中使用此方法定義了一份 Riak\Contracts\Connection
的實現(xiàn)。若你還不了解服務(wù)容器是如何運作的,不用擔(dān)心,我們很快會提到它。
此類位于 App\Providers
命名空間之下,因為這是 Laravel 中默認服務(wù)提供者所在的位置。然而,你可以隨自己的需要改變它。你的服務(wù)提供者可被置于任何 Composer 能自動加載的位置。
所以,若我們需要在服務(wù)提供者中注冊一個事件監(jiān)聽器,該怎么做?它應(yīng)該在 boot
方法中完成。這個方法會在所有的服務(wù)提供者注冊后才被調(diào)用,這能讓你使用框架中其他所有已注冊過的服務(wù)。
<?php namespace App\Providers;
use Event;
use Illuminate\Support\ServiceProvider;
class EventServiceProvider extends ServiceProvider {
/**
* 執(zhí)行注冊后的啟動服務(wù)。
*
* @return void
*/
public function boot()
{
Event::listen('SomeEvent', 'SomeEventHandler');
}
/**
* 在容器中注冊綁定。
*
* @return void
*/
public function register()
{
//
}
}
我們可以對 boot
方法中的依賴作類型提示。服務(wù)容器會自動注入任何你所需要的依賴:
use Illuminate\Contracts\Events\Dispatcher;
public function boot(Dispatcher $events)
{
$events->listen('SomeEvent', 'SomeEventHandler');
}
所有的服務(wù)提供者都在 config/app.php
此一配置文件中被注冊。此文件包含了一個 providers
數(shù)組,你可以在其中列出你所有服務(wù)提供者的名稱。此數(shù)組默認會列出一組 Laravel 的核心服務(wù)提供者。這些提供者啟動了 Laravel 的核心組件,例如郵件發(fā)送者、隊列、緩存及其他等等。
要注冊你的提供者,只要把它加入此數(shù)組:
'providers' => [
// 其他的服務(wù)提供者
'App\Providers\AppServiceProvider',
],
若你的提供者僅僅用于綁定注冊到服務(wù)容器,你可以選擇延緩其注冊,直到真正需要其中注冊的綁定才加載。延緩像這樣的提供者加載可增進應(yīng)用程序的性能,因為這樣就不用每個請求都從文件系統(tǒng)中將其加載。
要延緩提供者加載,將 defer
性質(zhì)設(shè)為 true
,并定義一個 provides
方法。 provides
方法應(yīng)返回提供者所注冊的服務(wù)容器綁定。
<?php namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider {
/**
* 指定是否延緩提供者加載。
*
* @var bool
*/
protected $defer = true;
/**
* 注冊服務(wù)提供者。
*
* @return void
*/
public function register()
{
$this->app->singleton('Riak\Contracts\Connection', function($app)
{
return new Connection($app['config']['riak']);
});
}
/**
* 取得提供者所提供的服務(wù)。
*
* @return array
*/
public function provides()
{
return ['Riak\Contracts\Connection'];
}
}
Laravel 編譯并保存所有由延緩服務(wù)提供者所提供的服務(wù)清單,以及其服務(wù)提供者的類名稱。只有在當(dāng)你嘗試解析其中的服務(wù)時, Laravel 才會加載服務(wù)提供者。