zoukankan      html  css  js  c++  java
  • 【反射】PHP的反射机制【原创】

    摘要:主要是参考列旭松、陈文著的《PHP核心技术与最佳实践》的1.5节。

    1.1 定义

    反射,直观理解就是根据到达地找到出发地和来源。比如说,给你一个光秃秃的对象,可以仅仅通过这个对象就能知道它所属的类以及拥有的方法。
    反射,指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取信息以及动态调用对象方法的功能称为反射API。

    1.2 获取对象属性和方法

    getMethods和getProperties分别用来获取对象的所有方法和所有属性,返回对象数组,然后通过getName来获取具体的方法和属性即可。但都是必须先通过反射获取类的原型, 即使用$reflect = new ReflectionObject($student);来获取对象的原型。
    下面是使用反射API来获取对象的属性和方法:
    运行:
    Setting age to 24
    Tom is male
    
    对象的属性有:
    name
    gender
    age
    Array
    (
        [0] => ReflectionProperty Object
            (
                [name] => name
                [class] => Person3
            )
    
        [1] => ReflectionProperty Object
            (
                [name] => gender
                [class] => Person3
            )
    
        [2] => ReflectionProperty Object
            (
                [name] => age
                [class] => Person3
            )
    
    )
    
    对象的方法有:
    say
    __set
    __get
    Array
    (
        [0] => ReflectionMethod Object
            (
                [name] => say
                [class] => Person3
            )
    
        [1] => ReflectionMethod Object
            (
                [name] => __set
                [class] => Person3
            )
    
        [2] => ReflectionMethod Object
            (
                [name] => __get
                [class] => Person3
            )
    
    )
    ------------------分隔线-----------------
    对象属性的关联数组:
    Array
    (
        [name] => Tom
        [gender] => male
        [age] => 24
    )
    对象属性列表所属的类:
    Person3类属性:
    Array
    (
        [name] =>
        [gender] =>
    )
    类的方法名组成的数组:
    Array
    (
        [0] => say
        [1] => __set
        [2] => __get
    )



    1.3 还原类的原型

    既然上面已经可以使用反射来获取对象的属性和方法了,那么再进一步,获取方法和属性的访问权限,那么就可以根据对象来获取类的原型了:
    PHP手册中关于反射API的有很多,可以说,反射完整的描述了一个类或者对象的原型。反射不仅可以用于类和对象,还可以用于函数、扩展模块、异常等。

    1.4 反射的invoke方法

    invoke方法是个很实用的方法,用来执行一个反射的方法:
    <?php
    /**
     * 使用反射API的invoke方法来执行反射的方法
     * Created by PhpStorm.
     * User: Administrator
     * Date: 2017/7/13
     * Time: 18:23
     */
    
    class HelloWorld
    {
        public function sayHelloTo($name) {
            return 'Hello ' . $name;
        }
    
    }
    
    // 获取反射的方法
    $method = new ReflectionMethod('HelloWorld', 'sayHelloTo');
    /** 上面的代码和下面注释的代码作用是一样的   */
    //$reflectionClass = new ReflectionClass('HelloWorld');
    //$method = $reflectionClass->getMethod('sayHelloTo');
    
    // 执行一个反射的方法
    echo $method->invoke(new HelloWorld(), 'Mike');    // Hello Mike
    


    其中的:
    作用相当于:
    $reflectionClass = new ReflectionClass('HelloWorld');
    $method = $reflectionClass->getMethod('sayHelloTo');



    1.5 动态代理

    使用反射的invoke方法,可以实现简单的动态代理:
    运行:
    方法前拦截记录 Log
    已经连接到数据库member
    方法后拦截
    方法前拦截记录 Log
    已经连接到数据库lottery
    方法后拦截

    这里简单说明一下,真正的操作类是MySql类,但SqlProxy类实现了根据动态传入参数,代替实际的类MySql类的运行,并且在方法运行前后进行拦截,并且可以动态改变类中的方法和属性,这就是简单的动态代理。

    1.6 反射的作用

    反射的用处:
    • 用于文档生成,因此可以用它对文件里的类进行扫描,逐个生成描述文档。
    • 用来做hook实现插件功能
    • 动态代理

    在平常开发中,用到反射的地方很有限,主要有两个地方,一个是对对象进行调试,另一个是获取类的信息。而在MVC和插件开发中,使用反射很常见,但是反射的消耗也很大,在可以找到替代方案的情况下,不要滥用反射。

    很多时候,善用反射能够保持代码的优雅和简洁,但反射也会破坏类的封装性,因为反射可以使本不应该暴露的方法或者属性被强制暴露了出来,这既是优点也是缺点。


  • 相关阅读:
    C++ 将对象写入文件 并读取
    IronPython fail to add reference to WebDriver.dll
    How to Capture and Decrypt Lync Server 2010 TLS Traffic Using Microsoft Tools
    .net code injection
    数学系学生应该知道的十个学术网站
    Difference Between Currency Swap and FX Swap
    Swift开源parser
    谈谈我对证券公司一些部门的理解(前、中、后台)[z]
    JDK8记FullGC时候Metaspace内存不会被垃圾回收
    JVM源码分析之JDK8下的僵尸(无法回收)类加载器[z]
  • 原文地址:https://www.cnblogs.com/linewman/p/9918116.html
Copyright © 2011-2022 走看看