ホームページ >バックエンド開発 >PHPチュートリアル >PHPクラスリフレクション実装の依存性注入処理の詳細説明

PHPクラスリフレクション実装の依存性注入処理の詳細説明

小云云
小云云オリジナル
2018-02-06 15:38:472401ブラウズ

PHP には完全なリフレクション API があり、クラス、インターフェイス、関数、メソッド、拡張機能をリバース エンジニアリングする機能を提供します。クラス リフレクションによって提供される機能を通じて、クラスがどのように定義されているか、クラスが持つ属性、メソッドが持つメソッド、メソッドが持つパラメーター、クラス ファイルへのパス、その他の非常に重要な情報を知ることができます。また、多くの PHP フレームワークがクラ​​スの反映により、クラス間の依存関係を自動的に解決する依存関係注入を実装できるため、日常の開発に大きな利便性がもたらされます。

この記事では、主にクラスリフレクションを使用して依存関係の注入(Dependency Injection)を実装する方法について説明します。PHPリフレクションのすべてのAPIを1つずつ説明するわけではありません。詳細なAPIリファレンス情報については、この記事で主に紹介されています。 PHP クラスを使用して依存関係注入プロセスを実装し、これに興味のある友人がこのエディターをフォローして学習できることを願っています。

より深く理解するために、クラスのリフレクションと、例を通して依存関係の注入を実装する方法を見てみましょう。

次のクラスは座標系内の点を表し、横座標 x と縦座標 y の 2 つの属性を持ちます。


/**
 * 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)
}

リフレクションを通じてプロパティを取得する


りー

1 つを返す ReflectionProperty オブジェクトで構成される配列


$reflectionClass->getProperties();

クラスで定義されたメソッドを反映します


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"
 }
}

ReflectionMethod オブジェクトで構成される配列を返します


$reflectionClass->getMethods();

getConstructor() コンストラクターの戻り値は 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"
 }
}

メソッドのパラメータを反映します


$constructor = $reflectionClass->getConstructor();

戻り値はReflectionParameterオブジェクトから構成される配列です。


$parameters = $constructor->getParameters();

依存関係の注入

さて、次に、make という関数を書き、クラス名を make 関数に渡し、クラスのオブジェクトを返します。make では、クラスの依存関係を注入するのに役立ちます。 、つまり、この例では、Point オブジェクトを Circle クラスのコンストラクターに挿入するのに役立ちます。


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

make メソッドを定義した後、それを使用して 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;
}

関連する推奨事項:

インスタンス分析 Laravel の依存関係注入

PHP は以下に基づいています反映の仕組み 自動依存性注入の実装方法を詳しく解説

PHPの依存性注入の解析方法

以上がPHPクラスリフレクション実装の依存性注入処理の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。