# 簡介
服務提供者是 Laravel 應用啟動的中心,你自己的應用以及所有 Laravel 的核心服務都是通過服務提供者啟動。
但是,我們所謂的“啟動”指的是什么?通常,這意味著注冊服務,包括注冊服務容器綁定、事件監聽器、中間件甚至路由。服務提供者是應用配置的中心。
如果你打開 Laravel 自帶的 `config/app.php` 文件,將會看到一個 `providers` 數組,這里就是應用所要加載的所有服務提供者類,當然,其中很多是延遲加載的,也就是說不是每次請求都會被加載,只有真的用到它們的時候才會加載。
通過本文檔,你將會學習如何編寫自己的服務提供者并在 Laravel 應用中注冊它們。
# 編寫服務提供者
所有的服務提供者都繼承自 `Illuminate\Support\ServiceProvider` 類。大部分服務提供者都包含兩個方法: `register` 和 `boot` 。在 `register` 方法中,你唯一要做的事情就是綁定服務到`服務容器`,不要嘗試在該方法中注冊事件監聽器,路由或者任何其它功能。
通過 Artisan 命令 `make:provider` 即可生成一個新的提供者:
~~~
php artisan make:provider RiakServiceProvider
~~~
## 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(Connection::class, function ($app) {
return new Connection(config('riak'));
});
}
}
~~~
該服務提供者只定義了一個 `register` 方法,并使用該方法在服務容器中定義了一個 `Riak\Connection` 的實現。如果你不知道服務容器是如何工作的,請參考`其文檔`。
**`bindings` 和 `singletons` 屬性**
如果你的服務提供者注冊了很多簡單的綁定,你可能希望使用 `bindings` 和 `singletons` 屬性來替代手動注冊每個容器綁定以簡化代碼。當服務提供者被框架加載后,會自動檢查這些屬性并注冊相應綁定:
~~~
<?php
namespace App\Providers;
use App\Contracts\ServerProvider;
use App\Contracts\DowntimeNotifier;
use Illuminate\Support\ServiceProvider;
use App\Services\PingdomDowntimeNotifier;
use App\Services\DigitalOceanServerProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* All of the container bindings that should be registered.
*
* @var array
*/
public $bindings = [
ServerProvider::class => DigitalOceanServerProvider::class,
];
/**
* All of the container singletons that should be registered.
*
* @var array
*/
public $singletons = [
DowntimeNotifier::class => PingdomDowntimeNotifier::class,
];
}
~~~
boot 方法
如果我們想要在服務提供者中注冊視圖 composer 該怎么做?這就要用到 `boot` 方法了。該方法在所有服務提供者被注冊以后才會被調用,這就是說我們可以在其中訪問框架已注冊的所有其它服務:
~~~
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
view()->composer('view', function () {
//
});
}
}
~~~
boot 方法的依賴注入
我們可以在 `boot` 方法中對依賴進行類型提示,`服務容器`會自動注入你所需要的依賴:
~~~
use Illuminate\Contracts\Routing\ResponseFactory;
public function boot(ResponseFactory $response){
$response->macro('caps', function ($value) {
//
});
}
~~~
# 注冊服務提供者
所有服務提供者都是通過配置文件 `config/app.php` 中進行注冊,該文件包含了一個列出所有服務提供者名字的 `providers` 數組,默認情況下,其中列出了所有核心服務提供者,這些服務提供者啟動 Laravel核心組件,比如郵件、隊列、緩存等等。
要注冊你自己的服務提供者,只需要將其追加到該數組中即可:
~~~
'providers' => [
// 其它服務提供者
App\Providers\ComposerServiceProvider::class,
],
~~~
# 延遲加載服務提供者
如果你的提供者僅僅只是在`服務容器`中注冊綁定,你可以選擇延遲加載該綁定直到注冊綁定的服務真的需要時再加載,延遲加載這樣的一個提供者將會提升應用的性能,因為它不會在每次請求時都從文件系統加載。
Laravel 編譯并保存所有延遲服務提供者提供的服務及服務提供者的類名。然后,只有當你嘗試解析其中某個服務時 Laravel 才會加載其服務提供者。
想要延遲加載一個提供者,設置 `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(Connection::class, function ($app) {
return new Connection($app['config']['riak']);
});
}
/**
* 獲取由提供者提供的服務.
*
* @return array
*/
public function provides()
{
return [Connection::class];
}
}
~~~
> 注:強烈推薦閱讀[深入理解控制反轉(IoC)和依賴注入(DI)](https://www.wandhi.com/post-865.html)深入理解服務容器和服務提供者的實現原理。
- 序言
- 新版特性
- 快速入門
- 升級指南
- 貢獻指南
- API文檔
- 安裝配置
- 目錄結構
- Homestead
- Valet
- 部署
- 核心概念
- 請求生命周期
- 服務容器
- 服務提供者
- 門面(Facades)
- 契約(Contracts)
- 框架基礎
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- 生成 URL
- Session
- 驗證
- 錯誤處理
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端腳手架
- 編譯前端資源(Laravel Mix)
- 安全系列
- 登錄認證
- API 認證
- 授權
- 加密
- 哈希
- 重置密碼
- 進階系列
- Artisan 控制臺
- 集合
- 廣播
- 緩存
- 事件
- 文件存儲
- 輔助函數
- 郵件
- 通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫操作
- 快速入門
- 查詢構建器
- 分頁
- 遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 關聯關系
- 集合
- 訪問器 & 修改器
- API 資源類
- 序列化
- 應用測試
- 快速入門
- HTTP 測試
- 瀏覽器測試
- 數據庫測試
- 模擬
- 官方擴展包
- Cashier(訂閱支付解決方案)
- Envoy(遠程操作解決方案)
- Horizon(隊列系統解決方案)
- Passport(API 認證解決方案)
- Scout(全文搜索解決方案)
- Socialite(第三方登錄解決方案)
- 相關下載
- Laravel 5.6 中文文檔離線版
- Laravel 5.6 一鍵安裝包