依賴注入 和 依賴注入容器 是不一樣的:php
你不須要一個容器來執行依賴注入,可是一個容器能夠幫助你。html
PHP-DI就是這樣作的:使依賴注入更加實用。git
下面是不使用DI的代碼大體工做的方式:github
下面是使用DI的代碼大體工做的方式:web
這是控制反轉的模式,被調用者和調用者之間的依賴性控制是相反的。工具
最主要的優勢是:在調用鏈頂部的那個老是你。你能夠控制全部依賴項,並徹底控制您的應用程序的工做方式,你能夠用另外一個(例如你建立的一個)來替換依賴項。this
例如,若是庫X使用 Logger Y,而你想讓它使用 Logger Z 呢?有了依賴注入,你就不須要更改庫X的代碼了。翻譯
那麼,使用PHP-DI的代碼是如何工做的:code
簡而言之,容器包含了建立和注入依賴的全部工做。htm
In short, the container takes away all the work of creating and injecting dependencies.
這是一個真實的例子,比較了一個經典的實現(使用new
或單例)和使用依賴注入。
假設你有:
class GoogleMaps { public function getCoordinatesFromAddress($address) { // calls Google Maps webservice } } class OpenStreetMap { public function getCoordinatesFromAddress($address) { // calls OpenStreetMap webservice } }
經典的作法是:
class StoreService { public function getStoreCoordinates($store) { $geolocationService = new GoogleMaps(); // or $geolocationService = GoogleMaps::getInstance() if you use singletons return $geolocationService->getCoordinatesFromAddress($store->getAddress()); } }
如今咱們想使用OpenStreetMap
而不是GoogleMaps
,咱們該怎麼作?
咱們必須更改StoreService
的代碼,以及全部其餘使用GoogleMaps
的類。
若是沒有依賴注入,你的類與它們的依賴緊耦合。
StoreService
如今使用依賴注入:
class StoreService { private $geolocationService; public function __construct(GeolocationService $geolocationService) { $this->geolocationService = $geolocationService; } public function getStoreCoordinates($store) { return $this->geolocationService->getCoordinatesFromAddress($store->getAddress()); } }
服務是使用接口 (Interface) 定義的:
interface GeolocationService { public function getCoordinatesFromAddress($address); } class GoogleMaps implements GeolocationService { ... class OpenStreetMap implements GeolocationService { ...
如今,StoreService
的用戶能夠決定使用哪一個實現。 它能夠隨時改變,沒必要重寫StoreService
。
StoreService
再也不與它的依賴緊耦合。
The
StoreService
is no longer tightly coupled to its dependency.
你可能會發現依賴注入會帶來一個缺點:你如今必須處理注入依賴關係。
這就是容器(Container),特別是PHP-DI能夠幫助你的地方。
而不是寫:
$geolocationService = new GoogleMaps(); $storeService = new StoreService($geolocationService);
你能夠寫:
$storeService = $container->get('StoreService');
並配置哪一個GeolocationService
PHP-DI應該經過配置自動注入到StoreService
中:
$container->set('GeolocationService', \DI\create('GoogleMaps'));
若是您改變主意,如今只須要改變一行配置。
感興趣嗎? 繼續閱讀開始使用PHP-DI指南!
p.s. 看到PHP-DI沒有中文文檔,第一次對着機翻瞎翻譯,若有疏漏敬請指正。