PHP如何實現依賴注入

2021-09-23 09:06:33 字數 3575 閱讀 7969

摘要: 控制反轉(inversion of control,英文縮寫為ioc)是框架的重要特徵。控制反轉(ioc)是一種思想,依賴注入(di)是實施這種思想的方法。

高層模組不應該依賴於底層模組,兩個都應該依賴抽象。

抽象不應該依賴於細節,細節應該依賴於抽象。

首先,我們來看一段**:

class a 

} class echot  

public

function echo() 

}   初始,我們都使用new 的方式在內部進行,echot類嚴重依賴於類a。每當類a變化時,echot類也得進行變化。

我們優化一下**

class echot   

可以看到,這樣做的話。很大程式上,我們對程式進行了解耦。類a無論你如何變動,echot類是不需要變動的。不再依賴於a。但是新問題又來了,我們現在只有a,萬一來了b,來了cdefg怎麼辦。

面向介面

inte***ce t 

class a 

} class b implements t 

} class echot  

public

function echo() 

}   將t抽象出為介面,這樣,echot類中的echo方法變成乙個抽象的方法,不到執行那一刻,不知道他們的method方式是怎麼實現的。

工廠

function gett($str)  

}   t要使用哪個是不明確的,因此,我們可以將其工廠化。【看上去很簡單,在di實際上有體現】

di(重點來了)

首先,我們看一下php的psr規範。

官方定義的介面

psr\container\containerinte***ce

包含兩個方法

function get($id);

function has($id);

仔細看上面的工廠,是不是和get($id)很一致,php官方將其定義為容器(container,我個人理解,就是乙個複雜的工廠)

dependency injection container

依賴注入容器

namespace core; 

use psr\container\containerinte***ce; 

class container implements containerinte***ce 

public

function build($classname) 

//反射 

$reflector = new \reflectionclass($classname); 

if (!$reflector->isinstantiable())  

// 檢查類是否可例項化, 排除抽象類abstract和物件介面inte***ce 

if (!$reflector->isinstantiable())  

/** @var \reflectionmethod $constructor 獲取類的建構函式 */ 

$constructor = $reflector->getconstructor(); 

// 若無建構函式,直接例項化並返回 

if (is_null($constructor))  

// 取構造函式引數,通過 reflectionparameter 陣列返回引數列表 

$parameters = $constructor->getparameters(); 

// 遞迴解析建構函式的引數 

$dependencies = $this->getdependencies($parameters); 

// 建立乙個類的新例項,給出的引數將傳遞到類的建構函式。 

$class =  $reflector->newinstanceargs($dependencies); 

$this->instance[$classname] = $class; 

return $class; 

} /** 

* @param array $parameters 

* @return array 

*/ public

function getdependencies(array $parameters) 

else  

} return $dependencies; 

} /** 

* @param \reflectionparameter $parameter 

* @return mixed 

* @throws \exception 

*/ public

function resolvenonclass(\reflectionparameter $parameter) 

throw new \exception($parameter->getname().' must be not null'); 

} /** 

* 參照psr-autoload規範 

* @param $path 

*/ public

function _autoload($path)  

return

false; 

}); 

} public

function get($id) 

if(class_exists($id)) 

throw new classnotfoundexception('class not found');  //實現的psr規範的異常 

} public

function has($id) 

}  使用示例

$container = new container('../');//假設這是路徑 

$echot = $container->get(\test\echot::class);     //假設echot類的命名空間是\test 

$echot->echo();  

這個時候,會出現乙個問題:

// 檢查類是否可例項化, 排除抽象類abstract和物件介面inte***ce 

if (!$reflector->isinstantiable())  

$this->aliases[$key] = $class; 

return $this; 

} //同時,我們需要在build的時候進行判斷是否為別名 

public

function build($classname) 

if(isset($this->aliases[$classname]))  

$classname = $this->aliases[$classname]; 

}  

就此,乙個簡單的php容器就實現了。

php 依賴注入的實現

當a類需要依賴於b類,也就是說需要在a類中例項化b類的物件來使用時候,如果b類中的功能發生改變,也會導致a類中使用b類的地方也要跟著修改,導致a類與b類高耦合。這個時候解決方式是,a類應該去依賴b類的介面,把具體的類的例項化交給外部。為了約束我們先定義乙個訊息介面 inte ce message i...

php依賴注入

依然是來自到喜啦的一道面試題,你知道什麼是依賴注入嗎?依賴注入 di 的概念雖然聽起來很深奧,但是如果你用過一些新興的php框架的話,對於di一定不陌生,因為它們多多少少都用到了依賴注入來處理類與類之間的依賴關係。class a 為什麼這種方案不可取呢?因為這樣的話,a與b就耦合在了一起,也就是說a...

如何理解php的依賴注入

之前寫過關於php依賴注入的文章。最近發現有的朋友對這個還是理解模糊,在這裡我想寫個簡單的例項幫助朋友們理解下。傳統的思路是應用程式用到乙個a類,就會建立a類並呼叫a類的方法,假如這個方法內需要乙個b類,就會建立b類並呼叫b類的方法,而這個方法內需要乙個c類,就會建立c類,接著做些其它工作。clas...