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 = 'C语言中文网'; 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('C语言中文网', 'http://c.biancheng.net/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, 'C语言中文网'); // 通过反射类调用指定实例的方法, 并传入参数 ?>
需要注意的是,在平常开发中,用到反射的地方并不多,主要是对对象进行调试,或者用来获取类的信息。在 MVC 和插件开发中,使用反射很常见,但是反射的消耗也很大,所有在可以找到替代方案的情况下,尽量不用反射。关于反射类更详细的介绍大家可以参考 https://www.php.net/manual/zh/book.reflection.php。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/24044.html