zoukankan      html  css  js  c++  java
  • PHP反射类,ReflectionClass、ReflectionMethod的使用

    PHP的反射类ReflectionClass、ReflectionMethod使用实例

    一、官方解释

    自PHP5版本后,PHP具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。

    二、首先,我们先来了解反射是什么?

    它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。

    其应用场景如:

    自动加载插件;

    自动生成文档;

    依赖注入;

    对象池;

    动态调用对象的方法,对象方法参数的检测等;

    用来扩充PHP语言。

    PHP反射API由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互。借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传递参数,动态调用类的静态方法。 反射API是PHP内建的OOP技术扩展,包括一些类,异常和接口,综合使用他们可用来帮助我们分析其它类,接口,方法,属性,方法和扩展。这些OOP扩展被称为反射。

    我们用的比较多的是 ReflectionClass类、ReflectionObject 和ReflectionMethod类,

    ReflectionClass 通过类名获取类的信息;

    ReflectionObject 通过类的对象获取类的信息;

    ReflectionMethod 获取一个方法的有关信息。

    其他的还有

    ReflectionException类

    ReflectionFunction类

    ReflectionExtension类

    ReflectionFunctionAbstract 类

    ReflectionGenerator类

    ReflectionParameter 类

    ReflectionProperty类

    ReflectionType类

    三、ReflectionClass,获取User类的属性及方法信息

    User类

    <?php
    
    class User
    {
        /**
         * 性别常量,1代表男,2代表女
         */
        const USER_GENDER_1 = 1;
        const USER_GENDER_2 = 2;
    
        /**
         * 创建静态私有的变量保存该类对象
         */
        private static $instance;
        /**
         * 用户全局唯一id
         *
         * @var string
         */
        protected $globalId;
        /**
         * 用户姓名
         *
         * @var string
         */
        protected $name;
        /**
         * 用户性别,1男;2女
         *
         * @var int
         */
        protected $gender;
        /**
         * 用户手机号
         *
         * @var string
         */
        protected $mobile;
    
        /**
         * @return string
         */
        public function getGlobalId(): string
        {
            return $this->globalId;
        }
    
        /**
         * @param string $globalId
         */
        public function setGlobalId(string $globalId): void
        {
            $this->globalId = $globalId;
        }
    
        /**
         * @return string
         */
        public function getName(): string
        {
            return $this->name;
        }
    
        /**
         * @param string $name
         */
        public function setName(string $name): void
        {
            $this->name = $name;
        }
    
        /**
         * @return int
         */
        public function getGender(): int
        {
            return $this->gender;
        }
    
        /**
         * @param int $gender
         */
        public function setGender(int $gender): void
        {
            $this->gender = $gender;
        }
    
        /**
         * @return string
         */
        public function getMobile(): string
        {
            return $this->mobile;
        }
    
        /**
         * @param string $mobile
         */
        public function setMobile(string $mobile): void
        {
            $this->mobile = $mobile;
        }
    
        /**
         * 获取用户的单例实现
         * @return User
         */
        public static function getInstance()
        {
            //判断实例有无创建,没有的话创建实例并返回,有的话直接返回
            if (!(self::$instance instanceof self)) {
                self::$instance = new self();
            }
            return self::$instance;
        }
    
    }
    PHP
    $className = "User";
    $class = new ReflectionClass($className); // 建立User类的反射类
    $instance  = $class->newInstanceArgs(); // 相当于实例化User类
    
    var_dump($class);
    var_dump($instance);
    
    $properties = $class->getProperties();
    
    var_dump($properties);
    
    foreach ($properties as $property) {
        echo $property->getName() . "
    ";
    }
    
    $private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);
    var_dump($private_properties);
    
    
    foreach ($properties as $property) {
        if ($property->isProtected()) {
            $docblock = $property->getDocComment();
            echo $docblock."
    ";
        }
    }
    
    $methods = $class->getMethods();
    var_dump($methods);
    
    $isExistMethod = $class->hasMethod("setMobile");
    var_dump($isExistMethod);
    $isExistMethod = $class->hasMethod("test");
    var_dump($isExistMethod);
    
    $method = $class->getMethod("setMobile");
    var_dump($method);
    
    
    //设置用户姓名
    $method = $class->getmethod('setName');// 获取User类中的setName方法
    $method->invokeArgs($instance, ["joshua317"]);
    
    //获取用户姓名
    $method = $class->getmethod('getName');// 获取User类中的getName方法
    $userName = $method->invoke($instance);//执行getName 方法
    var_dump($userName);
    
    
    $method = new ReflectionMethod('User', 'setName');
    if ($method->isPublic() && !$method->isStatic()) {
        echo "function is protected";
    }
    
    // 参数个数
    echo $method->getNumberOfParameters();
    
    // 参数对象数组
    $params = $method->getParameters();
    var_dump($params);
    
    //执行方法
    $method->invokeArgs($instance, ["joshua"]);
    //获取用户姓名
    $method = $class->getmethod('getName');// 获取User类中的getName方法
    $userName = $method->invoke($instance);//执行getName 方法
    var_dump($userName);
    PHP

    1.常量 Contants 2.属性 Property Names 3.方法 Method Names静态 4.属性 Static Properties 5.命名空间 Namespace 6.User类是否为final或者abstract 7.User类是否有某个方法

    接下来反射它,只要把类名"User"传递给ReflectionClass就可以了:

    $class = new ReflectionClass('User'); // 建立User这个类的反射类
    $instance  = $class->newInstanceArgs(); // 相当于实例化User类
    
    var_dump($class);
    var_dump($instance);
    PHP
    #结果如下:
    object(ReflectionClass)#1 (1) {
      ["name"]=>
      string(4) "User"
    }
    
    object(User)#2 (4) {
      ["globalId":protected]=>
      NULL
      ["name":protected]=>
      NULL
      ["gender":protected]=>
      NULL
      ["mobile":protected]=>
      NULL
    }
    
    
    3.1 获取属性(Properties):
    $properties = $class->getProperties();
    
    var_dump($properties);
    
    foreach ($properties as $property) {
        echo $property->getName() . "
    ";
    }
    //结果如下:
    array(5) {
      [0]=>
      object(ReflectionProperty)#3 (2) {
        ["name"]=>
        string(8) "instance"
        ["class"]=>
        string(4) "User"
      }
      [1]=>
      object(ReflectionProperty)#4 (2) {
        ["name"]=>
        string(8) "globalId"
        ["class"]=>
        string(4) "User"
      }
      [2]=>
      object(ReflectionProperty)#5 (2) {
        ["name"]=>
        string(4) "name"
        ["class"]=>
        string(4) "User"
      }
      [3]=>
      object(ReflectionProperty)#6 (2) {
        ["name"]=>
        string(6) "gender"
        ["class"]=>
        string(4) "User"
      }
      [4]=>
      object(ReflectionProperty)#7 (2) {
        ["name"]=>
        string(6) "mobile"
        ["class"]=>
        string(4) "User"
      }
    }
    
    instance
    globalId
    name
    gender
    mobile
    PHP

    默认情况下,ReflectionClass会获取到所有的属性,private 和 protected的也可以。如果只想获取到private属性,就要额外传个参数:

    $private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);
    var_dump($private_properties);
    //结果如下:
    array(1) {
      [0]=>
      object(ReflectionProperty)#8 (2) {
        ["name"]=>
        string(8) "instance"
        ["class"]=>
        string(4) "User"
      }
    }
    

    可用参数列表:

    ReflectionProperty::IS_STATIC
    
    ReflectionProperty::IS_PUBLIC
    
    ReflectionProperty::IS_PROTECTED
    
    ReflectionProperty::IS_PRIVATE
    PHP

    通过$property->getName()可以得到属性名。

    3.2 获取注释

    通过getDocComment可以得到写给property的注释。

    foreach ($properties as $property) {
        if ($property->isProtected()) {
            $docblock = $property->getDocComment();
            echo $docblock."
    ";
        }
    }
    结果如下:
    /**
         * 用户全局唯一id
         *
         * @var string
         */
    /**
         * 用户姓名
         *
         * @var string
         */
    /**
         * 用户性别,1男;2女
         *
         * @var int
         */
    /**
         * 用户手机号
         *
         * @var string
         */
    PHP
    3.3 获取类的方法
    getMethods() 来获取到类的所有methods。
    
    hasMethod(string)  是否存在某个方法
    
    getMethod(string)  获取方法
    PHP
    $methods = $class->getMethods();
    var_dump($methods);
    
    //结果如下:
    array(9) {
      [0]=>
      object(ReflectionMethod)#9 (2) {
        ["name"]=>
        string(11) "getGlobalId"
        ["class"]=>
        string(4) "User"
      }
      [1]=>
      object(ReflectionMethod)#10 (2) {
        ["name"]=>
        string(11) "setGlobalId"
        ["class"]=>
        string(4) "User"
      }
      [2]=>
      object(ReflectionMethod)#11 (2) {
        ["name"]=>
        string(7) "getName"
        ["class"]=>
        string(4) "User"
      }
      [3]=>
      object(ReflectionMethod)#12 (2) {
        ["name"]=>
        string(7) "setName"
        ["class"]=>
        string(4) "User"
      }
      [4]=>
      object(ReflectionMethod)#13 (2) {
        ["name"]=>
        string(9) "getGender"
        ["class"]=>
        string(4) "User"
      }
      [5]=>
      object(ReflectionMethod)#14 (2) {
        ["name"]=>
        string(9) "setGender"
        ["class"]=>
        string(4) "User"
      }
      [6]=>
      object(ReflectionMethod)#15 (2) {
        ["name"]=>
        string(9) "getMobile"
        ["class"]=>
        string(4) "User"
      }
      [7]=>
      object(ReflectionMethod)#16 (2) {
        ["name"]=>
        string(9) "setMobile"
        ["class"]=>
        string(4) "User"
      }
      [8]=>
      object(ReflectionMethod)#17 (2) {
        ["name"]=>
        string(11) "getInstance"
        ["class"]=>
        string(4) "User"
      }
    }
    PHP
    $isExistMethod = $class->hasMethod("setMobile");
    var_dump($isExistMethod);
    $isExistMethod = $class->hasMethod("test");
    var_dump($isExistMethod);
    
    //结果如下:
    bool(true)
    bool(false)
    PHP
    $method = $class->getMethod("setMobile");
    var_dump($method);
    //结果如下:
    object(ReflectionMethod)#18 (2) {
      ["name"]=>
      string(9) "setMobile"
      ["class"]=>
      string(4) "User"
    }
    PHP
    3.4 执行类的方法
    //设置用户姓名
    $method = $class->getmethod('setName');// 获取User类中的setName方法
    $method->invokeArgs($instance, ["joshua317"]);
    
    //获取用户姓名
    $method = $class->getmethod('getName');// 获取User类中的getName方法
    $userName = $method->invoke($instance);//执行getName 方法
    var_dump($userName);
    
    //结果如下:
    joshua317
    PHP

    四、ReflectionMethod,获取User类的某个方法的信息

    1.是否"public"、"protected"、"private" 、"static"类型 2.方法的参数列表 3.方法的参数个数 4.反调用类的方法

    // 获取方法修饰类型
    $method = new ReflectionMethod('User', 'getName');
    if ($method->isPublic() && !$method->isStatic()) {
        echo "function is public";
    }
    
    // 参数个数
    echo $method->getNumberOfParameters();
    
    // 参数对象数组
    $params = $method->getParameters();
    var_dump($params);
    
    //执行方法
    $method->invokeArgs($instance, ["joshua"]);
    //获取用户姓名
    $method = $class->getmethod('getName');// 获取User类中的getName方法
    $userName = $method->invoke($instance);//执行getName 方法
    var_dump($userName);
    
    //结果如下:
    function is public
    1
    array(1) {
      [0]=>
      object(ReflectionParameter)#18 (1) {
        ["name"]=>
        string(4) "name"
      }
    joshua
    PHP

     

  • 相关阅读:
    线性表的实现用通用方法实现线性表的初始化、求表长、插入元素、删除元素等
    用c++定义两个坐标点,计算两点间距离;进而计算线段的面积
    Java:学生信息的录入,各种排序,对文件的操作
    数组1 2 3 4 5 6 1(输入-1结束),奇数位的数逆序,偶数位数不变
    按层次遍历二叉树,用队列作为缓冲
    Chapter09"内核模式下的线程同步"之事件内核对象
    Chapter10“I/O设备的同步和异步”之打开和关闭设备
    CSDN博客积分系统
    探秘Java垃圾回收机制
    Chapter09“内核模式下的线程同步”之可等待的计时器内核对象
  • 原文地址:https://www.cnblogs.com/joshua317/p/15177649.html
Copyright © 2011-2022 走看看