PHP反射基础知识回顾

这篇文章主要介绍了PHP 反射的相关资料,帮助大家回顾和理解PHP的相关知识,感兴趣的朋友可以了解下

反射是编程语言的高级特性,能在运行时让代码有感知代码的能力。PHP自5起支持反射机制,其是各种OOP框架底层实现的重要支撑。

反射

从一个简单的例子理解反射:人有五官四肢,但鲜有人清楚人体内部的经脉走向、骨骼构造。如果你修仙顺利,在丹田深处练出元婴,那么就通过元婴透析身体内部的构造。理解内部构造后,还可以让元婴指引体内真气在经脉的流向,早日修成正果。

如其名,反射是(从镜子里)照出自身。我们写代码,告诉代码怎么运行,事件发生在编译期。代码运行期间,代码如何知道自己的结构以及能力呢?反射机制相当于代码的元婴,使代码能够感知自身结构,并可(部分)改变运行行为。

与运行时类型信息(Runtime Type Informatiion, RTTI)不同,反射重点在运行时检测、感知、改变自身的结构和行为。反射是元编程(metaprogramming)的重要组成部分。

PHP反射API

反射不是语法分析,不操作表达式、代码语句。反射获取的是代码的结构,即函数、类这些构件的结构。PHP中的反射API均以Reflection开头(接口Reflector除外),重点在函数和类两种结构。而函数可以看成类的成员函数(多一个隐式的this参数)或者静态成员函数(public类型),所以了解反射API可从类信息的ReflectionClass开始。

ReflectionClass提供了以下获取类基本信息的接口:

getProperties:获取成员变量/属性,返回一个ReflectionProperty数组;ReflectionProperty类中有对属性详细说明的API:是否默认属性(isDefault),是否私有属性(isPrivate)等。同时ReflectionClass还提供获取特定类别属性的API:getDefaultProperties,getStaticProperties;

getConstants:获取类中定义的常量;

getMethods:获取类中定义的方法,返回一个ReflectionMethod数组;ReflectionMethod将在下文讲解;

getInterfaces:获取类实现的接口;

getParentClass:获取父类的ReflectionClass实例。

在反射中,类、接口、特性不分家,所以ReflectionClass提供类型判定API:isInterface、isTrait。

除了以上基本信息,ReflectionClass(包括ReflectionMethod/ReflectionFunction)还提供了一些不可思议的能力:

getDocComment:获取类的文档注释信息;

getFilename:获取类定义的文件;

getStartLine: 获取类定义的起始行号;

getEndLine: 获取类定义的结束行号;

getModifiers:获取类定义的修饰符,其意义名字可通过Reflection::getModifierNames得到,例如:abstract,final。

如果说前述的类结构信息可以通过现有的API获取(method_exits/property_exits等),上面列出的功能基本上只能通过反射API获取(PHP文件中定义的类并且知道定义文件,可以利用token_get_all得到相同结果,但是实现非常复杂)。这些行为发生在运行期间。由此可见反射API在分析类结构信息功能上的强大。

除了ReflectionClass,ReflectionMethod和ReflectionFunction是另外反射中另外两个重要的类。函数(function)定义在类外部,方法(method)定义在类内部,两者其实同源,在反射API中有共同的父类:ReflectionFunctionAbstract。ReflectionFunctionAbstract有两者的大部分API,并且基本上是最重要的API。其中最值得关注的是其参数信息的API:getParameters。其获取函数的参数信息,返回一个ReflectionParameter数组。结合getParameters和ReflectionParameter,函数(方法)的结构基本上就清晰了。

API操作

知道人体构造和体内真气分布,你可以引导真气到手指,练成一阳指、六脉神剑、弹指神通、九阴白骨爪等;也可以让真气汇聚,冲破任督二脉,开辟洞天;还可以逆转全身经脉,练成*蟆功…内省的好处可见一斑。

反射让代码感知自身结构,有什么好处呢?反射API提供了三种在运行时对代码操作的能力:

设置访问控制权:setAccessible。可获取私有的方法/属性。注意:setAccessible只是让方法/成员变量可以invoke/getValue/setValue,并不代表类定义的访问存取权限改变;

调用函数/方法:invoke/invokeArgs。配合获取函数参数的API,可以安全的传参和调用函数,call_user_func(_array)的增强版;

不依赖构造函数生成实例:newInstanceWithoutConstructor。

以单例来说一下反射API的功能,单例类代码如下:

# foo.php
class Foo {
 private static $id;
 private static $instance;

 private function __construct() {
 ++ self::$id;
 fwrite(STDOUT, “construct, instance id: ” . self::$id . “\n”);
 }

 public static function getSingleton() {
 if (self::$instance === null) {
 self::$instance = new self();
 }
 return self::$instance;
 }
}

在Foo类中,构造函数是私有,获取实例只能通过getSingleton方法,并且获取到的是单例。但在反射API加持下,能获取多个实例:

$instance1 = Foo::getSingleton();
var_dump($instance1);

$class = new ReflectionClass(“Foo”);
$constructor = $class->getConstructor();
if ((ReflectionProperty::IS_PUBLIC & $constructor->getModifiers()) === 0) {
 $constructor->setAccessible(true);
}
$instance2 = $class->newInstanceWithoutConstructor();
$constructor->invoke($instance2);
var_dump($instance2);

# 脚本执行结果
construct, instance id: 1
object(Foo)#1 (0) {
}
construct, instance id: 2
object(Foo)#4 (0) {
}

我们成功的生成了两个实例,并调用构造函数完成对象初始化。如果没有反射API,这几乎是不可能完成的工作。

除了这三种操作,反射API几乎已无在运行时动态改变代码的行为。但作为动态语言,PHP内置了将数据转换成代码执行的能力(例如create_function/eval、动态函数名调用)。而PHP的好基友JavaScript则可以随时在运行时改变任意函数的行为:

PHP作为最好的语言,理应能做到在运行时动态增减/改变函数定义。这就需要用到另一个PHP核心开发者“Dmitry Zenovich”打造的大杀器:runkit拓展。这部分内容不属于反射,加之本人了解不深,不再详述。

对比

整理一下反射API和函数式API在功能上的差异:

PHP反射基础知识回顾

PHP反射基础知识回顾

总结

本文对PHP中的反射机制做了简要总结,并与在运行时获取代码信息的函数式API做了对比。即使你token_get_all用得再熟练,preg_match等文本操作用得再顺手,反射API仍有其独到一面,值得了解。如本人之前博文“PHP中的重载”所言,有了反射,function_exits/class_exits、call_user_func这些函数应该可以退休。但是考虑到兼容、使用便利、运行效率等因素,许多框架仍然依赖这些API。

感谢阅读,欢迎指正!

以上就是PHP反射知识回顾的详细内容,更多关于PHP 反射的资料请关注脚本之家其它相关文章!

来源:脚本之家

链接:https://www.jb51.net/article/195310.htm

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:SEO优化专员,转转请注明出处:https://www.chuangxiangniao.com/p/900506.html

(0)
上一篇 2025年1月4日 01:59:17
下一篇 2025年1月4日 01:59:45

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • php实现记事本案例

    这篇文章主要为大家详细介绍了php实现记事本案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了php实现记事本的具体代码,供大家参考,具体内容如下 记事本案例 要求:1)页面上有一个文本…

    2025年1月4日
    100
  • PHP实现限制域名访问的实现代码本地验证

    这篇文章主要介绍了PHP实现限制域名访问的实现代码,如果不是允许的域名不让使用,然后让客户购买认证即可,但本地验证加密一般都可以被破解,建议用远程验证,都收费了不差这点钱了,需要的朋友可以参考下 用PHP编写好的源码,如果不想被其它人直接利…

    编程技术 2025年1月4日
    200
  • PHP$O00OO0=urldecode&eval 解密记一次商业源码的去后门

    最近看到如下的php代码$O00OO0=urldecode(“%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%…

    编程技术 2025年1月4日
    200
  • PHP获取类私有属性的3种方法

    这篇文章主要介绍了PHP获取类私有属性的3种方法,帮助大家更好的理解和使用php,感兴趣的朋友可以了解下 今天在推上看到一条获取PHP类私有属性的推文,感觉很有意思: 顺着推文联想,还有其他方式吗?经过自己的测试及网上答案,总结出三种方法:…

    编程技术 2025年1月4日
    200
  • php实现图片压缩处理

    这篇文章主要为大家详细介绍了php实现图片压缩处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了php实现图片压缩处理的具体代码,供大家参考,具体内容如下 说明 在项目中,经常会遇到在前…

    编程技术 2025年1月4日
    200
  • 如何在PHP中读写文件

    这篇文章主要介绍了如何在PHP中读写文件,帮助大家更好的理解和学习php,感兴趣的朋友可以了解下 在PHP中读写文件,可以用到一下内置函数: 1.fopen(创建文件和打开文件) 语法: fopen(filename,mode) filen…

    编程技术 2025年1月4日
    200
  • PHP延迟静态绑定使用方法实例解析

    这篇文章主要介绍了PHP延迟静态绑定使用方法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 PHP的继承模型中有一个存在已久的问题,那就是在父类中引用扩展类的最终状态比较困难。我们…

    编程技术 2025年1月4日
    200
  • php autoload使用方法及步骤详解

    这篇文章主要介绍了PHP autoload使用方法及步骤详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 我们知道在PHP4里面,当我们使用一个类的时候,必须将该类所以文件使用inclu…

    编程技术 2025年1月4日
    200
  • PHP数组访问常用方法解析

    这篇文章主要介绍了PHP数组访问常用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1、如果使用的是索引方式的数组可以使用for循环来实现如下: for ( $i = 0; $i …

    编程技术 2025年1月4日
    200
  • XAMPP升级PHP版本实现步骤解析

    这篇文章主要介绍了XAMPP升级PHP版本实现步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 XAMPP(Apache+MySQL+PHP+PERL)是一个功能强大的建站集成软件包…

    编程技术 2025年1月4日
    200

发表回复

登录后才能评论

联系我们

156-6553-5169

在线咨询: QQ交谈

邮件:253000106@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

联系微信