Maison  >  Article  >  développement back-end  >  Tutoriel simple sur l'API de réflexion php

Tutoriel simple sur l'API de réflexion php

伊谢尔伦
伊谢尔伦original
2017-07-01 10:40:301042parcourir

En parlant d'API de réflexion, j'estime que l'API de réflexion en PHP est similaire au package java.lang.reflect en Java. Ils sont tous deux composés d'un ensemble de classes intégrées qui peuvent imprimer et analyser la classe. attributs et méthodes des membres. Peut-être avez-vous déjà appris les fonctions d'objet telles que get_class_vars(), mais l'utilisation de l'API de réflexion sera plus flexible et les informations de sortie seront plus détaillées.

Tout d'abord, nous devons savoir que l'API de réflexion n'est pas seulement utilisée pour vérifier les classes, elle comprend elle-même un ensemble de classes pour remplir diverses fonctions : les classes couramment utilisées sont les suivantes :

Classe de réflexion
Reflection类 可以打印类的基本信息,(通过提供的静态export()函数)
ReflectionMethod类 见名知意,打印类方法、得到方法的具体信息等
ReflectionClass类 用于得到类信息,比如得到类包含的方法,类本的属性,是不是抽象类等
ReflectionParameter类 显示参数的信息,可以动态得到已知方法的传参情况
ReflectionException类  用于显示错误信息
ReflectionExtension类 得到PHP的扩展信息,可以判断扩展是否存在等
Les informations de base de la classe peuvent être imprimées (via la fonction static export() fournie)
Classe ReflectionMethod Connaître la signification par son nom, imprimer les méthodes de classe, obtenir des informations spécifiques sur les méthodes, etc.
Classe ReflectionClass est utilisé pour obtenir des informations sur la classe, par exemple, obtenir les méthodes contenues dans la classe, les attributs de la classe, s'il s'agit d'une classe abstraite, etc.
Classe ReflectionParameter Afficher les informations sur les paramètres, vous pouvez obtenir dynamiquement l'état de transfert des paramètres des méthodes connues
est utilisé pour afficher le Message d'erreur
Classe ReflectionExtension Obtenez des informations sur l'extension PHP, vous pouvez déterminer si l'extension existe, etc.






La différence entre les informations d'impression traditionnelles et l'API de réflexion
Ce qui suit est Un programme de paramètres que j'ai écrit moi-même pour démontrer l'utilisation de la réflexion :

<?php

class Person
{
    //成员属性
    public $name;
    public $age; 

    //构造方法
    public function construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    //成员方法
    public function set_name($name)
    {
        $this->$name = $name;
    }

    public function get_name()
    {
        return $this->$name;
    }

    public function get_age()
    {
        return $this->$age;
    }

    public function get_user_info()
    {
        $info = &#39;姓名:&#39; . $this->name;
        $info .= &#39; 年龄:&#39; . $this->age;
        return $info;
    }
}

class Teacher extends Person
{
    private $salary = 0;

    public function construct($name, $age, $salary)
    {
        parent::construct($name, $age);
        $this->salary = $salary;
    }

    public function get_salary()
    {
        return $this->$salary;
    }

    public function get_user_info()
    {
        $info = parent::get_user_info();
        $info .= " 工资:" . $this->salary;
        return $info;
    }
}

class Student extends Person
{
    private $score = 0;

    public function construct($name, $age, $score)
    {
        parent::construct($name, $age);
        $this->score = $score;
    }

    public function get_score()
    {
        return $this->score;        
    }

    public function get_user_info()
    {
        $info = parent::get_user_info();
        $info .= " 成绩:" . $this->score;
        return $info;
    }
}

header("Content-type:text/html;charset=utf8;");
$te_obj = new Teacher(&#39;李老师&#39;, &#39;36&#39;, &#39;2000&#39;);
$te_info = $te_obj->get_user_info();

$st_obj = new Student(&#39;小明&#39;, &#39;13&#39;, &#39;80&#39;);
$st_info = $st_obj->get_user_info();

Nous utilisons d'abord var_dump(); Pour imprimer des informations simples sur la classe, il n'y a même pas de méthode, donc aucune autre information sur la natation ne peut être vue à partir de ces informations.

var_dump($te_obj);

object(Teacher)#1 (3) {
      ["salary":"Teacher":private]=>
          string(4) "2000"
      ["name"]=>
          string(9) "李老师"
      ["age"]=>
          string(2) "36"
}

 Reflection::export($obj);

Nous utilisons la méthode d'exportation intégrée fournie par Reflection pour imprimer les informations, comme indiqué ci-dessous :

Les informations imprimées sont relativement complètes, y compris les membres attributs, membres Méthode, informations de base de la classe, chemin du fichier, informations sur la méthode, attributs de la méthode, état de transfert des paramètres, nombre de lignes dans le fichier, etc. Un affichage relativement complet des informations sur la classe. On peut voir que var_dump() ou print_r ne peuvent afficher que de brèves informations sur la classe, et que de nombreuses informations ne peuvent pas être affichées du tout, elles ne peuvent donc être utilisées que pour un débogage simple. L'API de réflexion fournit plus d'informations sur la classe. ce qui peut être d'une grande aide.Nous connaissons la situation de l'appel de classes, ce qui est très pratique pour écrire des interfaces, en particulier pour appeler les interfaces d'autres personnes. Cela peut également aider au débogage en cas de problème.

object(Teacher)#1 (3) {
      ["salary":"Teacher":private]=>
          string(4) "2000"
      ["name"]=>
          string(9) "李老师"
      ["age"]=>
          string(2) "36"
}
Class [  class Person ] {
      @@ /usr/local/www/phptest/oop/reflaction.php 3-38
      - Constants [0] {
      }
      - Static properties [0] {
      }
      - Static methods [0] {
 }
  - Properties [2] {
        Property [  public $name ]
        Property [  public $age ]
  }

  - Methods [5] {
    Method [  public method construct ] {
      @@ /usr/local/www/phptest/oop/reflaction.php 10 - 14

      - Parameters [2] {
        Parameter #0 [  $name ]

.....

Utilisation spécifique de l'API de réflexion :

Les étudiants qui ont lu le code source du framework savent que tout Le framework peut être utilisé pour charger des plug-ins tiers, des bibliothèques de classes, etc. Dans l'exemple suivant, nous utilisons l'API de réflexion pour implémenter simplement cette fonction. J'ai appris le prototype de cet exemple dans un livre, après l'avoir compris, j'ai écrit un ensemble selon mes propres idées : Fonction à réaliser : Utiliser une classe pour dynamiquement. parcourir et appeler la classe Property Les objets et les classes peuvent charger librement les méthodes d'autres classes sans avoir à intégrer la classe dans le code existant ou à appeler manuellement le code de la bibliothèque de classes.
Convention : Chaque classe doit contenir une méthode de travail et peut faire abstraction d'une interface. Vous pouvez mettre les informations de chaque classe dans le fichier, ce qui est équivalent aux informations de chaque bibliothèque de classes, puis appeler la méthode de travail de chaque bibliothèque de classes via l'objet correspondant de la bibliothèque de classes Property enregistré par la classe.

Voici le code de base :

/*属性接口*/
interface Property
{
    function work();
}

class Person
{
    public $name;
    public function construct($name)
    {
        $this->name = $name;
    }
}

class StudentController implements Property
{
    //set方法,但需要Person对象参数
    public function setPerson(Person $obj_person)
    {
        echo &#39;Student &#39; . $obj_person->name;
    }

    //work方法简单实现
    public function work()
    {
        echo &#39;student working!&#39;;
    }
}

class EngineController implements Property
{
    //set方法
    public function setWeight($weight)
    {
        echo &#39;this is engine -> set weight&#39;;
    }

    public function setPrice($price)
    {
        echo "this is engine -> set price";
    }

    //work方法简单实现
    public function work()
    {
        echo &#39;engine working!&#39;;
    }
}

Ici, deux classes similaires sont définies pour implémenter l'interface Property, et toutes deux implémentent simplement work() La méthode de la classe StudentController est légèrement différente. Les paramètres nécessitent un objet Person. En même temps, nous pouvons utiliser des fichiers pour enregistrer les informations de chaque classe.

class Run
{
    public static $mod_arr = [];
    public static $config = [
        &#39;StudentController&#39; => [
            &#39;person&#39; => &#39;xiao ming&#39;
        ],
        &#39;EngineController&#39;  => [
            &#39;weight&#39; => &#39;500kg&#39;,
            &#39;price&#39;  => &#39;4000&#39;
        ]
    ];

    //加载初始化
    public function construct()
    {
        $config = self::$config;
        //用于检查是不是实现类
        $property = new ReflectionClass(&#39;Property&#39;);
        foreach ($config as $class_name => $params) {
            $class_reflect = new ReflectionClass($class_name);
            if(!$class_reflect->isSubclassOf($property)) {//用isSubclassOf方法检查是否是这个对象
                echo &#39;this is  error&#39;;
                continue;
            }

            //得到类的信息
            $class_obj = $class_reflect->newInstance();
            $class_method = $class_reflect->getMethods();

            foreach ($class_method as $method_name) {
                $this->handle_method($class_obj, $method_name, $params);
            }
            array_push(self::$mod_arr, $class_obj);
        }
    }

    //处理方法调用
    public function handle_method(Property $class_obj, ReflectionMethod $method_name, $params)
    {
        $m_name = $method_name->getName();
        $args = $method_name->getParameters();

        if(count($args) != 1 || substr($m_name, 0, 3) != &#39;set&#39;) {    
            return false;
        }
        //大小写转换,做容错处理
        $property = strtolower(substr($m_name, 3));
     
        if(!isset($params[$property])) {
            return false;
        }

        $args_class = $args[0]->getClass();
        echo &#39;<pre class="brush:php;toolbar:false">&#39;;
        if(empty($args_class)) {
            $method_name->invoke($class_obj, $params[$property]); //如果得到的类为空证明需要传递基础类型参数
        } else {
            $method_name->invoke($class_obj, $args_class->newInstance($params[$property])); //如果不为空说明需要传递真实对象
        }
    }
}

//程序开始
new Run();

À la fin de ce programme, Run startup appellera automatiquement le constructeur pour initialiser les autres propriétés membres de la bibliothèque de classes à charger, y compris l'initialisation et l'exécution des opérations de méthode correspondantes . Ceci vient de se terminer. L'attribut $mod_arr enregistre tous les objets de la classe appelante. Chaque objet contient des données et les objets inclus peuvent être parcourus pour appeler la méthode work().

Le programme est uniquement utilisé pour aider à comprendre la réflexion PAI. Chaque fonction n'est pas parfaite. Elle utilise de nombreuses classes et méthodes d'API de réflexion. Vous trouverez ci-dessous un résumé de chaque méthode. .

API Reflection Classes et fonctions communes fournies :

Les fonctions fournies ci-dessous ne sont pas toutes les fonctions couramment utilisées sont utilisées, et certaines fonctions ne sont pas utilisées du tout, nous avons donc écrit sur celles qui mentent. Si vous voulez toutes les voir, vous pouvez effectuer une recherche en ligne, il y en a beaucoup. Il n'est pas nécessaire de mémoriser l'ensemble des méthodes fournies, vous pouvez les consulter lorsque vous les utilisez.

1:Reflection
  public static export(Reflector r [,bool return])//打印类或方法的详细信息
  public static  getModifierNames(int modifiers)  //取得修饰符的名字

2:ReflectionMethod:
    public static string export()                       //打印该方法的信息
    public mixed invoke(stdclass object, mixed* args)   //调用对应的方法
    public mixed invokeArgs(stdclass object, array args)//调用对应的方法,传多参数
    public bool isFinal()        //方法是否为final
    public bool isAbstract()     //方法是否为abstract
    public bool isPublic()       //方法是否为public
    public bool isPrivate()      //方法是否为private
    public bool isProtected()    //方法是否为protected
    public bool isStatic()       //方法是否为static
    public bool isConstructor()  //方法是否为构造函数

3:ReflectionClass:
    public static string export()  //打印类的详细信息
    public string getName()        //取得类名或接口名
    public bool isInternal()       //类是否为系统内部类
    public bool isUserDefined()    //类是否为用户自定义类
    public bool isInstantiable()   //类是否被实例化过
    public bool hasMethod(string name)  //类是否有特定的方法
    public bool hasProperty(string name)//类是否有特定的属性
    public string getFileName()         //获取定义该类的文件名,包括路径名
    public int getStartLine()           //获取定义该类的开始行
    public int getEndLine()             //获取定义该类的结束行
    public string getDocComment()       //获取该类的注释
    public ReflectionMethod getConstructor()           //取得该类的构造函数信息
    public ReflectionMethod getMethod(string name)     //取得该类的某个特定的方法信息
    public ReflectionMethod[] getMethods()             //取得该类的所有的方法信息
    public ReflectionProperty getProperty(string name) //取得某个特定的属性信息
    public ReflectionProperty[] getProperties()        //取得该类的所有属性信息
    public array getConstants()                        //取得该类所有常量信息
    public mixed getConstant(string name)              //取得该类特定常量信息
    public ReflectionClass[] getInterfaces()           //取得接口类信息
    public bool isInterface()  //测试该类是否为接口
    public bool isAbstract()   //测试该类是否为抽象类

4:ReflectionParameter:
    public static string export()     //导出该参数的详细信息
    public string getName()           //取得参数名
    public bool isPassedByReference() //测试该参数是否通过引用传递参数
    public ReflectionClass getClass() //若该参数为对象,返回该对象的类名
    public bool isArray()             //测试该参数是否为数组类型
    public bool allowsNull()          //测试该参数是否允许为空
    public bool isOptional()          //测试该参数是否为可选的,当有默认参数时可选
    public bool isDefaultValueAvailable() //测试该参数是否为默认参数
    public mixed getDefaultValue()        //取得该参数的默认值

5:ReflectionExtension类
    public static  export()    //导出该扩展的所有信息
    public string getName()    //取得该扩展的名字
    public string getVersion() //取得该扩展的版本
    public ReflectionFunction[] getFunctions()   //取得该扩展的所有函数
    public array getConstants()  //取得该扩展的所有常量
    public array getINIEntries() //取得与该扩展相关的,在php.ini中的指令信息
}

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