Home  >  Article  >  Backend Development  >  PHP reflection API simple tutorial

PHP reflection API simple tutorial

伊谢尔伦
伊谢尔伦Original
2017-07-01 10:40:301112browse

Speaking of reflection API, I feel that the reflection API in PHP is similar to the java.lang.reflect package in Java. They are both composed of a set of built-in classes that can print and analyze class member attributes and methods. Maybe you have already learned object functions such as get_class_vars(), but using the reflection API will be more flexible and the output information will be more detailed.

First of all, we need to know that the reflection API is not only used to check classes, it itself includes a set of classes to complete various functions: commonly used classes are as follows:

Reflection class You can print basic information of the class (through the provided static export() function)
ReflectionMethod class See the name and know the meaning, print the class method, get the specific information of the method, etc.
ReflectionClass class is used to obtain class information, such as the methods contained in the class, the attributes of the class, and whether it is an abstract class Wait
ReflectionParameter class Display parameter information, you can dynamically obtain the parameter transfer status of known methods
ReflectionException class Used to display error messages
ReflectionExtension class Get PHP extension information, you can determine whether the extension exists, etc.






The difference between traditional printing information and reflection API
The following is A parameter program I wrote myself to demonstrate the use of reflection:

<?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();

We first use var_dump(); to print the class information, as shown below, you can see that it just prints out There is no simple information about the class, not even methods, so no other swimming information can be seen from such information.

var_dump($te_obj);

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

 

Reflection::export($obj);

We use the built-in export method provided by Reflection to print information, as shown below:

The printed information is relatively complete, including member properties and member methods. Basic information of the class, file path, method information, method attributes, parameter transfer status, number of lines in the file, etc. A relatively comprehensive display of class information. It can be seen that var_dump() or print_r can only display brief information about the class, and a lot of information cannot be displayed at all, so they can only be used for simple debugging. The reflection API provides more information about the class, which can be a good help. We know the situation of calling classes, which provides great convenience for writing interfaces, especially calling other people's interfaces. It can also help with debugging if something goes wrong.

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 ]

.....

Specific use of reflection API:

Students who have read the source code of the framework know that the framework can be loaded Third-party plug-ins, class libraries, etc. In the following example, we use reflection API to simply implement this function. I learned the prototype of this example from a book. After understanding it, I wrote a set according to my own ideas: Function to be realized: Use a class to dynamically traverse and call the Property class Objects and classes can freely load the methods of other classes without having to embed the class into existing code or manually call the class library code. Convention: Each class must contain a work method and can abstract an interface. You can put the information of each class in the file, which is equivalent to the information of each class library, and then call the work method of each class library through the corresponding object of the Property class library saved by the class.

The following is the basic code:

/*属性接口*/
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;;
    }
}

Two similar classes are defined here to implement the Property interface, and both simply implement the work() method StudentController Classes are slightly different. The parameters require Person objects. At the same time, we can use files to save information about each class. We can also use member attributes instead.

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();

At the end of this program, Run startup will automatically call the constructor to initialize other member properties of the class library to be loaded, including initialization and execution of corresponding method operations. Here we only complete the corresponding set method. The $mod_arr attribute saves all objects of the calling class. Each object contains data, and the included objects can be traversed to call the work() method.

The program is only used to assist in understanding reflection PAI. Each function is not perfect. It uses many reflection API classes and methods. There will be a summary of each method below.

Reflection API Common classes and functions provided:

The functions provided below are Not all commonly used functions are used, and some functions are not used at all, so we have written about the ones that lie. If you want to see all of them, you can search online, there are many. There is no need to memorize the set of methods provided, you can review them when you use them.

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中的指令信息
}

The above is the detailed content of PHP reflection API simple tutorial. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn