前言
Laravel使用IoC(Inversion of Control,控制倒轉(zhuǎn),這是一個設(shè)計模式,可以先查看下百科)容器這個強有力的工具管理類依賴。依賴注入(也是一種設(shè)計模式,一般用于實現(xiàn)IoC)是一個不用編寫固定代碼來處理類之間依賴的方法,相反的,這些依賴是在運行時注入的,這樣允許處理依賴時具有更大的靈活性。
理解 Laravel IoC容器是構(gòu)建強大應(yīng)用程序所必要的,也有助于Laravel 核心本身。下面話不多說了,來一起看看詳細的介紹吧。
基本用例
綁定一個類型到容器
IoC 容器有兩種方法來解決依賴關(guān)系:通過閉包回調(diào)或者自動解析。首先,我們來探究一下閉包回調(diào)。首先,需要綁定一個“類型”到容器中:
App::bind('foo', function($app) { return new FooBar; });
從容器中取得一個類型
$value = App::make('foo');
當執(zhí)行 App::make
方法,閉包函數(shù)被執(zhí)行并返回結(jié)果。
綁定一個”共享“類型到容器
有時,你只想將綁定到容器的類型處理一次,然后接下來從容器中取得的都應(yīng)該是相同實例:
App::singleton('foo', function() { return new FooBar; });
綁定一個已經(jīng)存在的類型實例到容器
你也可以使用instance方法,將一個已經(jīng)存在的對象接口綁定到容器中:
$foo = new Foo; App::instance('foo', $foo);
哪里去注冊綁定呢
IoC綁定,很像事件句柄或者路由過濾,通常在"bootstrap code(引導(dǎo)代碼)"之后完成。換句話說,它們在你的應(yīng)用程序準備處理請求,也即是在一個路由或者控制器被實際執(zhí)行之前執(zhí)行。和其他引導(dǎo)代碼一樣,start文件通常作為IoC綁定注冊一種方法。另外,你可以創(chuàng)建一個app/ioc.php(文件名不一定一樣)文件,并在start文件中包含它。
如果你的應(yīng)用程序有很大量IoC綁定,或者你想根據(jù)不同的分類將IoC綁定分割到不同的文件,你可以嘗試在服務(wù)提供器(見下面)中進行綁定
自動解析
取得一個類
IoC容器足夠強大,在許多場景下不需要任何配置就能取得類。例如
class FooBar { public function __construct(Baz $baz) { $this->baz = $baz; } } $fooBar = App::make('FooBar');
注意:我們雖然沒有在容器中注冊FooBar類,容器仍然可以取得該類,甚至自動注入Baz依賴!
當某個類型沒有綁定到容器,IoC容器將使用 PHP 的反射工具來檢查類和讀取構(gòu)造器的類型提示。使用這些信息,容器可以自動構(gòu)建類實例。
綁定一個接口實現(xiàn)
然而,在某些情況下,一個類可能依賴某個接口實現(xiàn),而不是一個 “具體的類”。當在這種情況下,App::bind
方法必須通知容器注入哪個接口實現(xiàn):
App::bind('UserRepositoryInterface', 'DbUserRepository');
現(xiàn)在考慮下這個控制器:
class UserController extends BaseController { public function __construct(UserRepositoryInterface $users) { $this->users = $users; } }
由于我們將 UserRepositoryInterface 綁定了具體類,DbUserRepository 在該控制器創(chuàng)建時將會被自動注入到該控制器。
實際用例
Laravel 提供了幾個方法使用 IoC 容器增強應(yīng)用程序可擴展性和可測試性。一個主要的例子是取得控制器。所有控制器都通過 IoC 容器取得,意味著可以在控制器構(gòu)造方法中對依賴的類型提示,它們將自動被注入。
對控制器的依賴關(guān)系做類型提示
class OrderController extends BaseController { public function __construct(OrderRepository $orders) { $this->orders = $orders; } public function getIndex() { $all = $this->orders->all(); return View::make('orders', compact('all')); } }
在這個例子中,OrderRepository 將會自動注入到控制器。意味著當 單元測試 模擬請求時,OrderRepository 將會綁定到容器以及注入到控制器中,允許無痛與數(shù)據(jù)庫層交互。
IoC 使用的其他例子