Facades 提供一個靜態(tài)接口給在應(yīng)用程序的 服務(wù)容器 中可以取用的類。Laravel 附帶許多 facades,甚至你可能已經(jīng)在不知情的狀況下使用過它們!Laravel 的「facades」作為在 IoC 容器里面的基礎(chǔ)類的靜態(tài)代理,提供的語法有簡潔、易表達(dá)的優(yōu)點(diǎn),同時(shí)維持比傳統(tǒng)的靜態(tài)方法更高的可測試性和彈性。
有時(shí),你或許會希望為應(yīng)用程序和擴(kuò)展包建立自己的 facades,所以讓我們來探索這些類的概念、開發(fā)和用法。
注意: 在深入了解 facades 之前,強(qiáng)烈建議你先熟悉 Laravel 服務(wù)容器.
在 Laravel 應(yīng)用程序的環(huán)境中,facade 是個提供從容器訪問對象的類。Facade
類是讓這個機(jī)制可以運(yùn)作的原因。Laravel 的 facades 和你建立的任何自定義 facades,將會繼承基類 Facade
。
你的 facade 類只需要去實(shí)現(xiàn)一個方法:getFacadeAccessor
。getFacadeAccessor
方法的工作是定義要從容器解析什么?;?Facade
利用 __callStatic()
魔術(shù)方法來從你的 facade 調(diào)用到解析出來的對象。
所以當(dāng)你對 facade 調(diào)用,例如 Cache::get
,Laravel 從服務(wù)容器解析緩存管理類出來,并對該類調(diào)用 get
方法。用專業(yè)口吻來說,Laravel Facades 是使用 Laravel 服務(wù)容器作為服務(wù)定位器的便捷語法。
在下面的例子,對 Laravel 緩存系統(tǒng)進(jìn)行調(diào)用。簡單看過去這代碼,有人可能會以為靜態(tài)方法 get
是對 Cache
類調(diào)用。
$value = Cache::get('key');
然而,如果我們?nèi)タ?Illuminate\Support\Facades\Cache
類,你將會看到它沒有靜態(tài)方法 get
:
class Cache extends Facade { /** * 取得組件的注冊名稱 * * @return string */ protected static function getFacadeAccessor() { return 'cache'; }}
Cache 類繼承基類 Facade
并定義一個 getFacadeAccessor()
方法。記住,這個方法的工作是返回服務(wù)容器綁定的名稱。
當(dāng)用戶在 Cache
的 facade 上參考任何的靜態(tài)方法,Laravel 會從服務(wù)容器解析被綁定的 cache
,并對該對象執(zhí)行被請求的方法 (在這個例子中, get
)。
所以我們的 Cache::get
調(diào)用可以被重寫成像這樣:
$value = $app->make('cache')->get('key');
記住,如果你在控制器有使用命名空間的情況下使用 facade,你會需要導(dǎo)入 facade 類進(jìn)入命名空間。所有的 facades 存在于全局命名空間:
<?php namespace App\Http\Controllers;use Cache;class PhotosController extends Controller { /** * 取得所有的應(yīng)用程序相片。 * * @return Response */ public function index() { $photos = Cache::get('photos'); // }}
為你自己的應(yīng)用程序或擴(kuò)展包建立 facade 是很簡單的。你只需要 3 個東西:
一個服務(wù)容器綁定。
一個 facade 類。
一個 facade 別名配置。
讓我們來看個例子。這里有一個定義為 PaymentGateway\Payment
的類。
namespace PaymentGateway;class Payment { public function process() { // }}
我們需要可以從服務(wù)容器解析出這個類。所以,讓我們來加上一個綁定到服務(wù)提供者:
App::bind('payment', function(){ return new \PaymentGateway\Payment;});
注冊這個綁定的好方式是建立新的 服務(wù)提供者 命名為 PaymentServiceProvider
,并把這個綁定加到 register
方法。然后你可以配置 Laravel 從 config/app.php
配置文件加載你的服務(wù)提供者。
接下來,我們可以建立我們自己的 facade 類:
use Illuminate\Support\Facades\Facade;class Payment extends Facade { protected static function getFacadeAccessor() { return 'payment'; }}
最后,如果我們希望,可以在 config/app.php
配置文件為 facade 加個別名到 aliases
數(shù)組?,F(xiàn)在我們可以在 Payment
類的實(shí)例上調(diào)用 process
方法。
Payment::process();
在 aliases
數(shù)組中的類在某些實(shí)例中不能使用,因?yàn)?PHP 將不會嘗試去自動加載未定義的類型提示類。如果 \ServiceWrapper\ApiTimeoutException
命別名為 ApiTimeoutException
,即便有異常被拋出,在 \ServiceWrapper
命名空間外面的 catch(ApiTimeoutException $e)
將永遠(yuǎn)捕捉不到異常。類似的問題在有類型提示的別名類一樣會發(fā)生。唯一的替代方案就是放棄別名并用 use
在每一個文件的最上面引入你希望類型提示的類。
單元測試是為什么現(xiàn)在 facades 采用這樣的工作方式的主要因素。事實(shí)上,可測試性甚至是 facades 存在的主要理由。想要獲得更多信息,請查看文檔的 模擬 facades 章節(jié)。
你將會在下面找到每一個 facade 和它的基礎(chǔ)類。這是個可以從一個給定的 facade 根源快速地深入 API 文檔的有用工具??蓱?yīng)用的 服務(wù)容器綁定 關(guān)鍵字也包含在里面。
更多建議: