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