# 架構 —— 服務提供者
## 1、簡介
服務提供者應用啟動的中心,你自己的應用以及所有Laravel的核心服務都是通過服務提供者啟動。
但是,我們所謂的”啟動“指的是什么?通常,這意味著注冊事物,包括注冊服務容器綁定、時間監聽器、中間件甚至路由。服務提供者是應用配置的中心。
如果你打開Laravel自帶的`config/app.php`文件,將會看到一個`providers`數組,這里就是應用所要加載的所有服務提供者類,當然,其中很多是延遲加載的,也就是說不是每次請求都會被加載,只有真的用到它們的時候才會加載。
本章里你將會學習如何編寫自己的服務提供者并在Laravel應用中注冊它們。
## 2、編寫服務提供者
所有的服務提供者繼承自`Illuminate\Support\ServiceProvider`類。繼承該抽象類要求至少在服務提供者中定義一個方法:`register`。在`register`方法內,你唯一要做的事情就是綁事物到[服務容器](http://laravelacademy.org/post/93.html),不要嘗試在其中注冊任何時間監聽器,路由或者任何其它功能。
通過Artisan命令`make:provider`可以簡單生成一個新的提供者:
~~~
php artisan make:provider RiakServiceProvider
~~~
### 2.1 register方法
正如前面所提到的,在`register`方法中只綁定事物到[服務容器](http://laravelacademy.org/post/93.html),而不要做其他事情,否則話,一不小心就能用到一個尚未被加載的服務提供者提供的服務。
現在讓我們來看看一個基本的服務提供者長什么樣:
~~~
<?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`的實現。如果你不太理解服務容器是怎么工作的,查看其[文檔](http://laravelacademy.org/post/93.html)。
### 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`方法中類型提示依賴,[服務容器](http://laravelacademy.org/post/93.html)會自動注冊你所需要的依賴:
~~~
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、延遲加載服務提供者
如果你的提供者僅僅只是在[服務容器](http://laravelacademy.org/post/93.html)中注冊綁定,你可以選在延遲加載該綁定直到注冊綁定真的需要時再加載,延遲加載這樣的一個提供者將會提升應用的性能,因為它不會在每次請求時都從文件系統加載。
想要延遲加載一個提供者,設置`defer`屬性為`true`并定義一個`provides`方法,該方法返回該提供者注冊的[服務容器](http://laravelacademy.org/post/93.html)綁定:
~~~
<?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才會加載其服務提供者。
> 擴展閱讀:[實例教程 —— 創建 Service Provider 測試示例](http://laravelacademy.org/post/796.html)
- 前言
- 序言
- 序言 ―― 發行版本說明
- 序言 ―― 升級指南
- 序言 ―― 貢獻代碼
- 開始
- 開始 ―― 安裝及配置
- 開始 ―― Laravel Homestead
- 基礎
- 基礎 ―― HTTP路由
- 基礎 ―― HTTP 中間件
- 基礎 ―― HTTP 控制器
- 基礎 ―― HTTP 請求
- 基礎 ―― HTTP 響應
- 基礎 ―― 視圖
- 基礎 ―― Blade模板
- 架構
- 架構 ―― 一次請求的生命周期
- 架構 ―― 應用目錄結構
- 架構 ―― 服務提供者
- 架構 ―― 服務容器
- 架構 ―― 契約
- 架構 ―― 門面
- 數據庫
- 數據庫 ―― 起步
- 數據庫 ―― 查詢構建器
- 數據庫 ―― 遷移
- 數據庫 ―― 填充數據
- Eloquent ORM
- Eloquent ORM ―― 起步
- Eloquent ORM ―― 關聯關系
- Eloquent ORM ―― 集合
- Eloquent ORM ―― 調整器
- Eloquent ORM ―― 序列化
- 服務
- 服務 ―― 用戶認證
- 服務 ―― Artisan 控制臺
- 服務 ―― Laravel Cashier(交易)
- 服務 ―― 緩存
- 服務 ―― 集合
- 服務 ―― Laravel Elixir
- 服務 ―― 加密
- 服務 ―― 錯誤&日志
- 服務 ―― 事件
- 服務 ―― 文件系統/云存儲
- 服務 ―― 哈希
- 服務 ―― 幫助函數
- 服務 ―― 本地化
- 服務 ―― 郵件
- 服務 ―― 包開發
- 服務 ―― 分頁
- 服務 ―― 隊列
- 服務 ―― Redis
- 服務 ―― Session
- 服務 ―― Envoy 任務運行器(SSH任務)
- 服務 ―― 任務調度
- 服務 ―― 測試
- 服務 ―― 驗證