服務(wù)提供者應(yīng)用啟動(dòng)的中心,你自己的應(yīng)用以及所有Laravel的核心服務(wù)都是通過服務(wù)提供者啟動(dòng)。
但是,我們所謂的”啟動(dòng)“指的是什么?通常,這意味著注冊(cè)事物,包括注冊(cè)服務(wù)容器綁定、時(shí)間監(jiān)聽器、中間件甚至路由。服務(wù)提供者是應(yīng)用配置的中心。
如果你打開Laravel自帶的config/app.php
文件,將會(huì)看到一個(gè)providers
數(shù)組,這里就是應(yīng)用所要加載的所有服務(wù)提供者類,當(dāng)然,其中很多是延遲加載的,也就是說不是每次請(qǐng)求都會(huì)被加載,只有真的用到它們的時(shí)候才會(huì)加載。
本章里你將會(huì)學(xué)習(xí)如何編寫自己的服務(wù)提供者并在Laravel應(yīng)用中注冊(cè)它們。
所有的服務(wù)提供者繼承自Illuminate\Support\ServiceProvider
類。繼承該抽象類要求至少在服務(wù)提供者中定義一個(gè)方法:register
。在register
方法內(nèi),你唯一要做的事情就是綁事物到服務(wù)容器,不要嘗試在其中注冊(cè)任何時(shí)間監(jiān)聽器,路由或者任何其它功能。
通過Artisan命令make:provider
可以簡(jiǎn)單生成一個(gè)新的提供者:
php artisan make:provider RiakServiceProvider
正如前面所提到的,在register
方法中只綁定事物到服務(wù)容器,而不要做其他事情,否則話,一不小心就能用到一個(gè)尚未被加載的服務(wù)提供者提供的服務(wù)。
現(xiàn)在讓我們來看看一個(gè)基本的服務(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(config('riak'));
});
}
}
該服務(wù)提供者只定義了一個(gè)register
方法,并使用該方法在服務(wù)容器中定義了一個(gè)Riak\Contracts\Connection
的實(shí)現(xiàn)。如果你不太理解服務(wù)容器是怎么工作的,查看其文檔。
如果我們想要在服務(wù)提供者中注冊(cè)視圖composer該怎么做?這就要用到boot
方法了。該方法在所有服務(wù)提供者被注冊(cè)以后才會(huì)被調(diào)用,這就是說我們可以在其中訪問框架已注冊(cè)的所有其它服務(wù):
<?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 () {
//
});
}
/**
* 在容器中注冊(cè)綁定.
*
* @return void
*/
public function register()
{
//
}
}
我們可以在boot
方法中類型提示依賴,服務(wù)容器會(huì)自動(dòng)注冊(cè)你所需要的依賴:
use Illuminate\Contracts\Routing\ResponseFactory;
public function boot(ResponseFactory $factory){
$factory->macro('caps', function ($value) {
//
});
}
所有服務(wù)提供者都是通過配置文件config/app.php
中進(jìn)行注冊(cè),該文件包含了一個(gè)列出所有服務(wù)提供者名字的providers
數(shù)組,默認(rèn)情況下,其中列出了所有核心服務(wù)提供者,這些服務(wù)提供者啟動(dòng)Laravel核心組件,比如郵件、隊(duì)列、緩存等等。
要注冊(cè)你自己的服務(wù)提供者,只需要將其追加到該數(shù)組中即可:
'providers' => [
// 其它服務(wù)提供者
App\Providers\AppServiceProvider::class,
],
如果你的提供者僅僅只是在服務(wù)容器中注冊(cè)綁定,你可以選在延遲加載該綁定直到注冊(cè)綁定真的需要時(shí)再加載,延遲加載這樣的一個(gè)提供者將會(huì)提升應(yīng)用的性能,因?yàn)樗粫?huì)在每次請(qǐng)求時(shí)都從文件系統(tǒng)加載。
想要延遲加載一個(gè)提供者,設(shè)置defer
屬性為true
并定義一個(gè)provides
方法,該方法返回該提供者注冊(cè)的服務(wù)容器綁定:
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider{
/**
* 服務(wù)提供者加是否延遲加載.
*
* @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)你嘗試解析其中某個(gè)服務(wù)時(shí)Laravel才會(huì)加載其服務(wù)提供者。
更多建議: