php的反射机制是什么 如何组织反射机制中的各种对象关系

问:PHP里反射机制是什么?

答:php的反射机制其实是比较高等一点的知识点了,是php5之后才加入这个功能,你既然了解到了这一点,就说明你对php的运用有相当一段时间了。反射机制其实就是“透视”+“规划”。为什么这么说呢,白话形容这个功能就是,不需要看源代码,只需要把类名或者对象传给反射类,然后就能获取到类的相关信息,例如常量、方法,甚至注释,这就是透视你的一切。然后呢就能策反你,让你为我所有,去调用我想调用的你的方法。这就是规划。

 

问:那整套反射机制里面是怎么运作的呢?

答:首先要说明的我们这里不是php手册,我们只针对反射机制的应用,做的一套非常实用的技巧,会根据里面所关联到的知识做一个梳理。

根据官方给出来的反射介绍,第一个需要知道的知识点就是,reflection类,这个类就两个静态方法,一个export(该方法导出一个反射对象的信息,包含两个参数,一个是反射类对象,另一个是个bool型,决定是否返回值,若返回值得类型是字符串)方法,另一个getModifierNames(这个方法是获取方法的修饰符的名称,只有一个参数,该参数是一个整型,叫标志位,是由反射方法对象的getModifiers方法获取的)

关于反射机制中我们最常用的一个类就是ReflectionClass,官方给出的注释是报告了一个类的相关信息,我们直接把一个完整的类名传给他,就能获得一个反射类对象(该对象超级牛逼,能透视能策反我们传给他的类)。但是这里需要知道的是,作为一个能导出类信息的反射类必须继承官方给提供的接口,这个接口叫reflector,他规定了所有的反射类要实现两个方法,一个静态方法export()用来导出类信息,另一个是魔术方法__toString()当要以字符串形式输出对象时触发。So,ReflectionClass继承了reflector并实现了这两个方法。除此之外,该类还实现了很多功能,(都是静态方法),所以时候他很牛逼。

下面我们以直接上代码,来介绍我们常用的那些方法。

首先我们来创建一个正常的业务类。我们然后来反射他

class User{

    const ROLE = 'Students';

    public $username = '';

    private $password = '';

    public function __construct($username, $password)

    {

        $this->username = $username;

        $this->password = $password;

    }

    /**

     * 获取用户名

     * @return string

     */

    public function getUsername()

    {

        return $this->username;

    }

    /**

     * 设置用户名

     * @param string $username

     */

    public function setUsername($username)

    {

        $this->username = $username;

    }

    /**

     * 获取密码

     * @return string

     */

    private function getPassword()

    {

        return $this->password;

    }

    /**

     * 设置密码

     * @param string $password

     */

    private function setPassowrd($password)

    {

        $this->password = $password;

    }

}

以上是我们的业务类代表,有常量,有公私属性,有公私方法。下面我们来反射他,透视他,策反他。

这里就是我们常用的方法了。

$class = new ReflectionClass('Extend\User');//传入一个完整的类名得到一个反射对象。

 

$properties = $class->getProperties(); //该方法可传入一个参数用来选择属性类型,获取User类的所有属性,返回ReflectionProperty的数组

 

$property = $class->getProperty('password'); //传入一个属性名称,获取类的一个属性的相关信息ReflectionProperty对象 获取User类的password属性ReflectionProperty,上面数组中的元素都是这种的

 

//要注意的是需要注意获取静态成员和非静态属性所使用的方法不一样

 

ReflectionClass::getStaticProperties — 获取静态(static)属性

ReflectionClass::getStaticPropertyValue — 获取静态(static)属性的值

 

$methods = $class->getMethods();   //该方法可以传入一个标识用来选择方法类型从而获取一组方法,获取User类的所有方法,返回ReflectionMethod数组

 

$method = $class->getMethod('getUsername');  //传入一个方法名获取类的一个方法的相关信息ReflectionMethod对象 获取User类的getUsername方法的ReflectionMethod,上面的数组里面的元素全是这种。

$constants = $class->getConstants();   // 获取所有常量,返回常量定义数组,不用管可见性如何定义。常量名是数组的键,常量的值是数组的值。

 

$constant = $class->getConstant('ROLE');   //该方法传入常量的名称,返回常量的值。 获取ROLE常量

 

$namespace = $class->getNamespaceName();  //该方法没有参数,返回类的命名空间

 

$comment_class = $class->getDocComment();  //该方法没有参数,获取类的在定义之前的注释,如果不存在文档注释则返回false 获取User类的注释文档,即定义在类之前的注释

 

$instance = $class->newInstance('youyou', '***');  //通过这个方法可以创建一个新对象(这就是策反了,为我所用),参数会传给构造方法能。 创建User类的实例

需要注意的是如果类的构造函数不是 public 的将会导致一个 ReflectionException

当 args 指定了一个或多个参数,而类不具有构造函数时,将导致一个 ReflectionException

 

 

以上便是ReflectionClass常用的几个反射类常用的方法,更多的可以查看api文档,多数是get,is,has等形式的方法。

 

接下来我们聊一下有ReflectionClass类延伸(继承)出来的另一个类ReflectionObject。这个类报告了一个对象的相关信息。(回忆一下,ReflectionClass的作用是报告一个类的相关信息)这个类自己重写了__construct()、export(静态)两个方法,其他的都是继承来的

 

关于反射就只能到这了么,不显然不是,反射机制可以反射的对象还有很多(需要注意的是他们都是继承了Reflector这个接口)。

例如:  ReflectionClassConstant ===》报告类常量信息的类(能自行构建,或通过getReflectionConstant方法返回对象)

ReflectionZendExtension ===》报告Zend扩展信息的类(只能自行构建)

ReflectionExtension ===》报告扩展信息的类(只能构建)

ReflectionFunctionAbstract ===》报告抽象功能的类(常作反射方法或函数的父类)

ReflectionParameter ===》报告方法或函数参数信息的类(可以自行创建,但多数都是使用反射函数,反射方法对象的父类对象抽象功能中getParameters方法获取参数反射对象数组,里面元素就是这个对象)

ReflectionProperty ===》报告类属性信息的类(可以自行构建,也可以通过ReflectionClass::getProperty来获取对象)

---------------------------------以下就不是直接以Reflector为父类的了---------------------------------------

 

ReflectionMethod ===》报告类方法信息的类(父类是抽象功能类 ReflectionFunctionAbstract,实现Reflector接口。可以通过ReflectionClass::getMethod获取,也可以自行构建 )

ReflectionFunction ===》报告函数信息的类(父类是抽象功能类ReflectionFunctionAbstract,实现Reflector接口。只能自行构建,支持传入闭包函数变量)

ReflectionType ===》报告函数、类方法的参数或者返回值的类型(这个是在参数反射对象(或返回值反射对象---这个好像没有)之后调用的getType,即ReflectionParameter::getType这个方法,生成ReflectionType对象)

ReflectionGenerator ===》报告生成器信息的类(该类自行构建,需要传入一个生成器。在ReflectionFunctionAbstract::isGenerator方法可以判别函数是否为生成器函数)

ReflectionException ===》反射异常类,继承自Exception基类

----------------------------------------以上便是反射机制中用到的全部对象了---------------------------------

 

从上面的对象我们可以看到,反射机制是非常之强大,能够反射的元素有很多,并且为他们创建了对象,从而能导出想对应的信息。例如:类、对象、属性、类常量、类方法、函数、参数、扩展、zend扩展,生成器,还有一个专门的异常类。本文并不是像php手册那样去一样样的教授怎么用,而是讲述反射机制怎么理解,如何去运用,最终的落实执行,还是需要读者自行在查手册之后去编写代码,这些方法,大部分人是记不住记不全的,只要写的多了,大体上就知道哪些常用,怎么用了,靠慢慢积累,当然如果你能全部记住并熟练使用,那你相当牛逼了,但要知道,会使用这些,为你项目所用才是真正的目的。

下面说几个注意事项:

当你通过newInstance创建原来的类实例或者直接调用里面的方法时:

1:直接访问 protected 或则 private 的属性或者方法会抛出异常,需要调用指定的 ReflectionProperty 或则 ReflectionMethod 对象 setAccessible(true)方法才能访问非公有成员。同时修改非公有成员的访问权限只作用于当前的反射类的实例

2:需要注意获取静态成员和非静态成员所使用的方法不一样

3:获取父类成员的方法和一般的不一样

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值