首页 > 编程笔记 > PHP笔记

PHP反射机制

PHP 自 5.0 版本以后添加了反射机制,其中包含了一套强大的反射 API,允许在 PHP 运行环境中,访问或使用类、方法、属性、参数和注释等,其功能十分强大,经常用于高扩展的 PHP 框架、自动加载插件、自动生成文档,甚至可以用来扩展 PHP 语言。

因为反射机制是 PHP 內建的 OOP 扩展,为语言本身自带的特性,所以不需要额外添加扩展或者配置就可以使用。反射 API 会基于类、方法、属性、参数等维护相应的反射类,已提供相应的调用 API。如下表所示:

类型 说明
Reflector Reflector 是一个接口,被所有可导出的反射类所实现(implement)
Reflection 反射(reflection)类
ReflectionClass 报告了一个类的有关信息
ReflectionZendExtension 报告Zend扩展的相关信息
ReflectionExtension 报告了PHP扩展的有关信息
ReflectionFunction 报告了一个函数的有关信息
ReflectionFunctionAbstract ReflectionFunction 的父类
ReflectionMethod 报告了一个方法的有关信息
ReflectionObject 报告了一个对象(object)的相关信息
ReflectionParameter 取回了函数或方法参数的相关信息
ReflectionProperty 报告了类的属性的相关信息

如何使用反射

假设我们定义了一个 Websit 类,示例代码如下所示:
<?php
    namespace Site;
    /**
     * Website 类
     */
    class Website{
        public $name;
        private $url;
        const TITLE = '新宝库';
        public function __construct($name, $url){
            $this->name = $name;
            $this->url = $url;
        }
        public function getName(){
            return $this->name;
        }
        /**
         * 获取连接
         * @return [type] [description]
         */
        private function getUrl(){
            return $this->url;
        }
    }
?>
想要获取 Websit 类中的属性或者方法,首先需要建立这个类的反射类实例,通过反射类的实例即可获取类中的属性或方法。不管类中定义的成员权限声明是否为 public,都可以获取到。示例代码如下所示:
<?php
    $class          = new \ReflectionClass('Site\\Website');  // 以类名 Website 作为参数,即可创建 Website 类的反射类
    $properties     = $class->getProperties();      // 以数组的形式返回 Website 类的所有属性
    $property       = $class->getProperty('name');  // 获取 Website 类的 name 属性
    $methods        = $class->getMethods();         // 以数组的形式返回 Website 类的所有方法
    $method         = $class->getMethod('getName'); // 获取 Website 类的 getName 方法
    $constants      = $class->getConstants();       // 以数组的形式获取所有常量
    $constant       = $class->getConstant('TITLE'); // 获取 TITLE 常量
    $namespace      = $class->getNamespaceName();   // 获取类的命名空间
    $comment_class  = $class->getDocComment();      // 获取 Website 类的注释文档,即定义在类之前的注释
    $comment_method = $class->getMethod('getUrl')->getDocComment();  // 获取 Website 类中 getUrl 方法的注释文档
?>
运行上面的代码即可获取 Website 类的相应信息,这里就不再一一打印出来了,大家可以自行尝试打印。

另外,不仅可以通过反射类访问类的方法和属性,还可以创建原来类的实例或者直接调用类里面的方法。示例代码如下所示:
<?php
    $class    = new \ReflectionClass('Site\\Website');         // 创建 Website 类的反射类
    $instance = $class->newInstance('新宝库', 'https://www.xinbaoku.com/php/');    // 创建 Website 类的实例
    $instance->getName();  // 调用 Website 类的 getName 方法
    $class->getProperty('name')->setValue($instance, 'C语言');  // 通过反射类设置 name 的属性值
    $value    = $class->getProperty('name')->getValue($instance);  // 通过反射类获取 name 的属性值
    $value    = $class->getMethod('getUrl')->invoke($instance);    // 通过反射类调用指定实例的方法,还可传入响应参数,如面下一行所示
    // $value = $class->getMethod('getUrl')->invoke($instance, '新宝库');    // 通过反射类调用指定实例的方法, 并传入参数
?>
需要注意的是,在平常开发中,用到反射的地方并不多,主要是对对象进行调试,或者用来获取类的信息。在 MVC 和插件开发中,使用反射很常见,但是反射的消耗也很大,所有在可以找到替代方案的情况下,尽量不用反射。关于反射类更详细的介绍大家可以参考 https://www.php.net/manual/zh/book.reflection.php

所有教程

优秀文章