国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

淺析PHP類的反射來實現依賴注入過程

2024-05-05 00:02:17
字體:
來源:轉載
供稿:網友

PHP具有完整的反射 API,提供了對類、接口、函數、方法和擴展進行逆向工程的能力。通過類的反射提供的能力我們能夠知道類是如何被定義的,它有什么屬性、什么方法、方法都有哪些參數,類文件的路徑是什么等很重要的信息。也正式因為類的反射很多PHP框架才能實現依賴注入自動解決類與類之間的依賴關系,這給我們平時的開發帶來了很大的方便。 本文主要是講解如何利用類的反射來實現依賴注入(Dependency Injection),并不會去逐條講述PHP Reflection里的每一個API,詳細的API參考信息請查閱官方文檔

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

下面這個類代表了坐標系里的一個點,有兩個屬性橫坐標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)*/

通過上面這個實例我簡單描述了一下如何利用PHP類的反射來實現依賴注入,Laravel的依賴注入也是通過這個思路來實現的,只不過設計的更精密大量地利用了閉包回調來應對各種復雜的依賴注入。

源碼分享:https://github.com/kevinyan815/php_reflection_dependency_injection_demo/blob/master/reflection.php


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 灌阳县| 兴宁市| 剑阁县| 平和县| 中宁县| 特克斯县| 隆德县| 怀宁县| 永清县| 乌拉特前旗| 正镶白旗| 隆化县| 无为县| 泰州市| 兴宁市| 辽宁省| 石首市| 兴宁市| 渭源县| 霍山县| 高淳县| 怀仁县| 广东省| 长垣县| 云浮市| 锡林浩特市| 正定县| 桐城市| 白银市| 北流市| 大方县| 沙湾县| 巴塘县| 阿克陶县| 乐陵市| 宜丰县| 丰镇市| 环江| 巴林右旗| 凉城县| 大方县|