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

小云云
Libérer: 2023-03-19 22:22:01
original
2377 Les gens l'ont consulté

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;
  }
}
Copier après la connexion

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);
  }
}
Copier après la connexion

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"
}
Copier après la connexion

Constante qui reflète la classe


$reflectionClass->getConstants();
Copier après la connexion

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


array(1) {
 ["PI"]=>
 float(3.14)
}
Copier après la connexion

Obtenir des propriétés par réflexion


$reflectionClass->getProperties();
Copier après la connexion

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"
 }
}
Copier après la connexion

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


$reflectionClass->getMethods();
Copier après la connexion

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"
 }
}
Copier après la connexion

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();
Copier après la connexion

Paramètres de la méthode Reflection


$parameters = $constructor->getParameters();
Copier après la connexion

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"
 }
}
Copier après la connexion

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;
}
Copier après la connexion

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)*/
Copier après la connexion

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!