PHP類的反射實現依賴注入過程詳解

來源:互聯網
上載者:User
PHP具有完整的反射 API,提供了對類、介面、函數、方法和擴充進行逆向工程的能力。通過類的反射提供的能力我們能夠知道類是如何被定義的,它有什麼屬性、什麼方法、方法都有哪些參數,類檔案的路徑是什麼等很重要的資訊。也正式因為類的反射很多PHP架構才能實現依賴注入自動解決類與類之間的依賴關係,這給我們平時的開發帶來了很大的方便。

本文主要是講解如何利用類的反射來實現依賴注入(Dependency Injection),並不會去逐條講述PHP Reflection裡的每一個API,詳細的API參考資訊請查閱官方文檔本文主要和大家介紹PHP類的反射來實現依賴注入過程以及相關知識點分享,對此有興趣的朋友跟著小編學習下吧,希望能協助到大家。

為了更好地理解,我們通過一個例子來看類的反射,以及如何?依賴注入。

下面這個類代表了座標系裡的一個點,有兩個屬性橫座標x和縱座標y。


/** * Class Point */class Point{  public $x;  public $y;  /**   * Point constructor.   * @param int $x horizontal value of point's coordinate   * @param int $y vertical value of point's coordinate   */  public function __construct($x = 0, $y = 0)  {    $this->x = $x;    $this->y = $y;  }}

接下來這個類代表圓形,可以看到在它的建構函式裡有一個參數是Point類的,即Circle類是依賴與Point類的。


class Circle{  /**   * @var int   */  public $radius;//半徑  /**   * @var Point   */  public $center;//圓心點  const PI = 3.14;  public function __construct(Point $point, $radius = 1)  {    $this->center = $point;    $this->radius = $radius;  }    //列印圓點的座標  public function printCenter()  {    printf('center coordinate is (%d, %d)', $this->center->x, $this->center->y);  }  //計算圓形的面積  public function area()  {    return 3.14 * pow($this->radius, 2);  }}

ReflectionClass

下面我們通過反射來對Circle這個類進行反向工程。

把Circle類的名字傳遞給reflectionClass來執行個體化一個ReflectionClass類的對象。


$reflectionClass = new reflectionClass(Circle::class);//傳回值如下object(ReflectionClass)#1 (1) { ["name"]=> string(6) "Circle"}

反射出類的常量


$reflectionClass->getConstants();

返回一個由常量名稱和值構成的關聯陣列


array(1) { ["PI"]=> float(3.14)}

通過反射擷取屬性


$reflectionClass->getProperties();

返回一個由ReflectionProperty對象構成的數組


array(2) { [0]=> object(ReflectionProperty)#2 (2) {  ["name"]=>  string(6) "radius"  ["class"]=>  string(6) "Circle" } [1]=> object(ReflectionProperty)#3 (2) {  ["name"]=>  string(6) "center"  ["class"]=>  string(6) "Circle" }}

反射出類中定義的方法


$reflectionClass->getMethods();

返回ReflectionMethod對象構成的數組


array(3) { [0]=> object(ReflectionMethod)#2 (2) {  ["name"]=>  string(11) "__construct"  ["class"]=>  string(6) "Circle" } [1]=> object(ReflectionMethod)#3 (2) {  ["name"]=>  string(11) "printCenter"  ["class"]=>  string(6) "Circle" } [2]=> object(ReflectionMethod)#4 (2) {  ["name"]=>  string(4) "area"  ["class"]=>  string(6) "Circle" }}

我們還可以通過getConstructor()來單獨擷取類的構造方法,其傳回值為一個ReflectionMethod對象。


$constructor = $reflectionClass->getConstructor();

反射出方法的參數


$parameters = $constructor->getParameters();

其傳回值為ReflectionParameter對象構成的數組。


array(2) { [0]=> object(ReflectionParameter)#3 (1) {  ["name"]=>  string(5) "point" } [1]=> object(ReflectionParameter)#4 (1) {  ["name"]=>  string(6) "radius" }}

依賴注入

好了接下來我們編寫一個名為make的函數,傳遞類名稱給make函數返回類的對象,在make裡它會幫我們注入類的依賴,即在本例中幫我們注入Point對象給Circle類的構造方法。


//構建類的對象function make($className){  $reflectionClass = new ReflectionClass($className);  $constructor = $reflectionClass->getConstructor();  $parameters = $constructor->getParameters();  $dependencies = getDependencies($parameters);    return $reflectionClass->newInstanceArgs($dependencies);}//依賴解析function getDependencies($parameters){  $dependencies = [];  foreach($parameters as $parameter) {    $dependency = $parameter->getClass();    if (is_null($dependency)) {      if($parameter->isDefaultValueAvailable()) {        $dependencies[] = $parameter->getDefaultValue();      } else {        //不是選擇性參數的為了簡單直接賦值為字串0        //針對構造方法的必須參數這個情況        //laravel是通過service provider註冊closure到IocContainer,        //在closure裡可以通過return new Class($param1, $param2)來返回類的執行個體        //然後在make時回調這個closure即可解析出對象        //具體細節我會在另一篇文章裡面描述        $dependencies[] = '0';      }    } else {      //遞迴解析出依賴類的對象      $dependencies[] = make($parameter->getClass()->name);    }  }  return $dependencies;}

定義好make方法後我們通過它來幫我們執行個體化Circle類的對象:


$circle = make('Circle');$area = $circle->area();/*var_dump($circle, $area);object(Circle)#6 (2) { ["radius"]=> int(1) ["center"]=> object(Point)#11 (2) {  ["x"]=>  int(0)  ["y"]=>  int(0) }}float(3.14)*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.