Maison  >  Article  >  développement back-end  >  Explication détaillée du processus d'injection de dépendances pour l'implémentation de la réflexion de classe PHP

Explication détaillée du processus d'injection de dépendances pour l'implémentation de la réflexion de classe PHP

小云云
小云云original
2018-02-06 15:38:472388parcourir

PHP dispose d'une API de réflexion complète, offrant la possibilité d'effectuer de l'ingénierie inverse sur des classes, des interfaces, des fonctions, des méthodes et des extensions. Grâce aux capacités fournies par la réflexion de classe, nous pouvons savoir comment la classe est définie, quels attributs elle possède, de quelles méthodes elle dispose, quels paramètres possède la méthode, quel est le chemin d'accès au fichier de classe et d'autres informations très importantes. C'est également grâce à la réflexion des classes que de nombreux frameworks PHP peuvent implémenter l'injection de dépendances pour résoudre automatiquement les dépendances entre les classes, ce qui apporte une grande commodité à notre développement quotidien.

Cet article explique principalement comment utiliser la réflexion de classe pour implémenter l'injection de dépendances (Injection de dépendances). Il ne décrira pas chaque API de PHP Reflection une par une. Pour des informations détaillées de référence sur l'API, veuillez vous référer à la documentation officielle. Cet article est principalement et Nous présenterons la réflexion de la classe PHP pour réaliser le processus d'injection de dépendances et partager les points de connaissances associés. Les amis qui sont intéressés par cela peuvent suivre l'éditeur pour apprendre.

Pour une meilleure compréhension, examinons la réflexion en classe et comment implémenter l'injection de dépendances à travers un exemple.

La classe suivante représente un point dans le système de coordonnées et possède deux attributs : abscisse x et ordonnée 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;
  }
}

La classe suivante représente un cercle. Vous pouvez voir qu'il y a un paramètre dans son constructeur qui est de la classe Point, c'est-à-dire que la classe Circle est. dépendant de la classe 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

Ensuite, nous utilisons la réflexion pour procéder à l'ingénierie inverse de la classe Circle.

Passez le nom de la classe Circle à réflexionClass pour instancier un objet de la classe ReflectionClass.


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

Constante qui reflète la classe


$reflectionClass->getConstants();

Renvoie un An tableau associatif composé de noms et de valeurs constantes


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

Obtenir des propriétés par réflexion


$reflectionClass->getProperties();

Renvoie un tableau composé d'objets 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"
 }
}

Reflète les méthodes définies dans la classe


$reflectionClass->getMethods();

Renvoie un tableau d'objets 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"
 }
}

Nous pouvons également obtenir la méthode constructeur de la classe séparément via getConstructor (), Sa valeur de retour est un objet ReflectionMethod.


$constructor = $reflectionClass->getConstructor();

Paramètres de la méthode Reflection


$parameters = $constructor->getParameters();

La valeur de retour est un tableau d'objets ReflectionParameter .


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

Injection de dépendances

Bon, nous écrivons ensuite une fonction appelée make et passons la classe Le nom est l'objet de la classe renvoyé par la fonction make. Dans make, cela nous aidera à injecter les dépendances de la classe, c'est-à-dire que, dans ce cas, cela nous aidera à injecter l'objet Point dans le constructeur de la classe 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;
}

Après avoir défini la méthode make, nous l'utilisons pour nous aider à instancier des objets de la classe 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)*/

Recommandations associées :

Analyse d'instance de l'injection de dépendances de Laravel

Explication détaillée de la méthode PHP d'injection automatique de dépendances basée sur un mécanisme de réflexion

Comment analyser l'injection de dépendance PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn