PHPが反射機構に基づいて自動依存注入を実現する方法の詳細

4879 ワード

本論文では,反射機構に基づくPHPの自動依存注入を実現する方法を例示した.皆さんの参考にしてください.具体的には以下の通りです.
注入に依存するのは制御反転とも呼ばれ、フレームワークを使ったことがある人はよく知られているはずだ.多くの人は名前を見るととても高いものだと思って、それを眺めて退き、今日は暇を見つけて研究して、彼の神秘的なベールを解いた.くだらないことは言わないで、直接コードをつけます;

/**
*
*    ,             。
*
*/
class Ioc {
  //         
  public static function getInstance($className) {
    $paramArr = self::getMethodParams($className);
    return (new ReflectionClass($className))->newInstanceArgs($paramArr);
  }
  /**
   *       
   * @param [type] $className [  ]
   * @param [type] $methodName [    ]
   * @param [type] $params   [     ]
   * @return [type]       [description]
   */
  public static function make($className, $methodName, $params = []) {
    //       
    $instance = self::getInstance($className);
    //                
    $paramArr = self::getMethodParams($className, $methodName);
    return $instance->{$methodName}(...array_merge($paramArr, $params));
  }
  /**
   *         ,         
   * @param [type] $className  [description]
   * @param [type] $methodsName [description]
   * @return [type]       [description]
   */
  protected static function getMethodParams($className, $methodsName = '__construct') {
    //         
    $class = new ReflectionClass($className);
    $paramArr = []; //     ,     
    //            
    if ($class->hasMethod($methodsName)) {
      //       
      $construct = $class->getMethod($methodsName);
      //            
      $params = $construct->getParameters();
      if (count($params) > 0) {
        //       
        foreach ($params as $key => $param) {
          if ($paramClass = $param->getClass()) {
            //         
            $paramClassName = $paramClass->getName();
            //       
            $args = self::getMethodParams($paramClassName);
            $paramArr[] = (new ReflectionClass($paramClass->getName()))->newInstanceArgs($args);
          }
        }
      }
    }
    return $paramArr;
  }
}


上記のコードはphpの反射関数を用いてコンテナクラスを作成し,このクラスを用いて他のクラスの依存注入機能を実現した.上の依存注入は2つに分けられ,1つは構造関数の依存注入であり,1つは方法の依存注入である.次の3つのクラスを使用してテストを行います.

class A {
  protected $cObj;
  /**
   *            B  A,A  C
   * @param C $c [description]
   */
  public function __construct(C $c) {
    $this->cObj = $c;
  }
  public function aa() {
    echo 'this is A->test';
  }
  public function aac() {
    $this->cObj->cc();
  }
}
class B {
  protected $aObj;
  /**
   *           
   * @param A $a [      A]
   */
  public function __construct(A $a) {
    $this->aObj = $a;
  }
  /**
   * [          ]
   * @param C   $c [    C]
   * @param string $b [            ]
   * @return [type]  [description]
   */
  public function bb(C $c, $b) {
    $c->cc();
    echo "\r
"; echo 'params:' . $b; } /** * * @return [type] [description] */ public function bbb() { $this->aObj->aac(); } } class C { public function cc() { echo 'this is C->cc'; } }

コンストラクション関数の依存注入のテスト

//   Ioc   B    ,B       A ,A       C 。
$bObj = Ioc::getInstance('B');
$bObj->bbb(); //   :this is C->cc ,         。
//   $bObj
var_dump($bObj);
//     ,    B  A  ,A  C  ,        。
object(B)#3 (1) {
 ["aObj":protected]=>
 object(A)#7 (1) {
  ["cObj":protected]=>
  object(C)#10 (0) {
  }
 }
}


試験方法依存注入

Ioc::make('B', 'bb', ['this is param b']);
//     ,          。
this is C->cc
params:this is param b


上記の2つの例から、オブジェクトを作成したりメソッドを呼び出したりするときに、クラスやメソッドがそのクラスに依存していることを知る必要はありません.反射メカニズムを使用すると、必要なクラスを自動的に注入することができます.
まとめ
はい、上のコードを見ると簡単だと思いますが、phpの反射メカニズムを熟知していれば、注入に依存して実現するのは難しくありません.上のコードは理解しやすいように書かれているので、簡単な除暴は、実際のプロジェクトでは簡単ではありません.例えば、注入されたクラスとパラメータを構成します.例えば、インスタンス化されたクラスをキャッシュします.次にクラスのインスタンスが必要な場合は、再初期化する必要がなく、直接使用できます.しかし、原理を信じて理解して、他のものはプロジェクトの需要に従って自分で改善することができます.
PHPについてもっと兴味のある読者は、「phpオブジェクト向けプログラミング入門教程」、「PHP基本文法入門教程」、「PHP演算と演算子用法総括」、「PHPネットワークプログラミング技巧総括」、「PHP配列(Array)操作技巧大全」、「php文字列(string)用法総括」、「php+mysqlデータベース操作入門チュートリアル」および「php一般データベース操作テクニック要約」
ここで述べたことが皆さんのPHPプログラム設計に役立つことを願っています.