Laravel 的核心概念包括:服務容器、服務提供者、門面(Facades)、契約(Contracts)。
服務容器是Laravel 的核心,是一個IoC 容器,是管理類依賴和運行依賴注入的有力工具。
服務提供者則提供服務並綁定服務至服務容器。是所有Laravel 應用程序引導啟動的中心所在。
Facades 為應用程序的服務容器中可用的類提供了一個「靜態」接口。它實際上是服務容器中那些底層類的「靜態代理」。
Laravel 的契約(Contracts )是一系列框架用來定義核心服務的接口。
不管是契約還是門面都可以創建出強大的、容易測試的Laravel 應用程序。
0x00 服務容器
Laravel 的核心就是一個IoC 容器,該容器提供了整個框架中需要的一系列服務。
IoC(Inversion Of Control)控制反轉,是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。IoC容器會根據類的依賴需求,自動在註冊、綁定的一堆實例中搜尋符合的依賴需求,並自動注入到構造函數參數中去。通過控制反轉,對像在被創建的時候,由一個調控系統內所有對象的外界實體,將其所依賴的對象的引用傳遞給它。也可以說,依賴被注入到對像中。這就是依賴注入(Dependency Injection, DI)。依賴注入實質上是指:類的依賴通過構造器或在某些情況下通過「setter」方法進行「注入」。
如何實現與服務容器的綁定?
幾乎所有服務容器的綁定都是在服務提供者中進行的。在服務提供者內部,可以通過$this->app 來訪問容器的實例。
綁定的方式包括:
-
簡單綁定
-
綁定一個單例
-
綁定實例
-
綁定接口到實現
-
情境綁定
-
綁定包括原始數據在內的初始數據
-
標記
其中,標記能夠針對某種類別的所有做綁定。
如何從服務容器解析出對象?
綁定後可以從服務容器中解析出對象才能夠使用。解析方法包括:
-
通過make 方法,接收一個你想要解析的類或者接口
-
通過數組方式從容器中解析對象
-
自動注入
自動注入實例
下面的例子中,在控制器的構造函數中對應用程序定義的Repository 使用類型提示。這樣Repository 實例會被自動解析並註入到類中:
users = $users; } /** *顯示指定ID的用戶信息。 * * @param int $id * @return Response */ public function show($id) { // } }
0x01 服務提供者
Laravel 中,包括應用程序,以及所有的Laravel 核心服務,都是通過服務提供者引導啟動的。所謂的「引導啟動」指的是註冊事務,包括註冊服務容器綁定,事件監聽器,中間件,甚至路由。
所有服務提供者都需要繼承Illuminate\Support\ServiceProvider 類。大多數服務提供者都包含register 和boot 方法。register 方法中,只能將事務綁定到服務容器。不應該在register 方法中嘗試註冊任何事件監聽器,路由或者任何其他功能。可以為服務提供者的boot 方法設置類型提示。服務容器會自動注入需要的任何依賴。boot 方法將在所有其他服務提供者均已註冊之後調用。
所有服務提供者都在config/app.php 配置文件中註冊。可以選擇推遲服務提供者的註冊,直到真正需要註冊綁定時,這樣可以提供應用程序的性能。
0x02 門面(Facades)
Facades 工作原理
在Laravel 應用中,一個facade 就是一個提供訪問容器中對象的類。其中核心的部件就是Facade 類。不管是Laravel 自帶的Facades ,還是用戶自定義的Facades ,都繼承自Illuminate\Support\Facades\Facade 類。
Facade 基類使用__callStatic() 魔術方法在你的Facades 中延遲調用容器中對應對象的方法,在下面的例子中,調用了Laravel 的緩存系統。在代碼裡,我們可能認為是Cache 類中的靜態方法get 被調用了:
$user]); } }
注意在代碼的最上面,我們導入的是Cache facade 。這個facade 其實是我們獲取底層Illuminate\Contracts\Cache\Factory 接口實現的一個代理。我們通過這個facade 調用的任何方法,都會被傳遞到Laravel 緩存服務的底層實例中。
如果我們看一下Illuminate\Support\Facades\Cache 這個類,你會發現類中根本沒有get 這個靜態方法:
class Cache extends Facade { /** *獲取組件在容器中註冊的名稱。 * * @return string */ protected static function getFacadeAccessor() { return 'cache'; } }
其實,Cache facade 是繼承了Facade 基類,並且定義了getFacadeAccessor() 方法。這個方法的作用是返回服務容器中對應名字的綁定內容。當用戶調用Cache facade 中的任何靜態方法時, Laravel 會解析到服務容器中綁定的鍵值為cache 實例對象,並調用這個對像對應的方法(在這個例子中就是get 方法)。
0x03 契約(Contracts)
如何使用契約?
Laravel 中的許多類型的類都是通過服務容器解析出來的。包括控制器、事件監聽器、中間件、任務隊列,甚至路由的閉包。所以說,要獲得一個契約的實現,你只需要解析在類的構造函數中相應的類型約束即可。
例如,看看這個事件監聽器,當事件監聽器被解析時,服務容器會從構造函數里讀取到類型約束,並註入對應的值。
redis = $redis; } /** *處理事件。 * * @param OrderWasPlaced $event * @return void */ public function handle(OrderWasPlaced $event) { // } }