首页 > 作文

PHP反射基础知识回顾

更新时间:2023-04-08 23:41:08 阅读: 评论:0

反射是编程语言的高级特性,能在运行时让代码有感知代码的能力。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:getdefaultpropertiesgetstaticpropertiesgetconstants:获取类中定义的常量;getmethods:获取类中定义的方法,返回一个reflectionmethod数组;reflectionmethod将在下文讲解;getinterfaces:获取类实现的接口;getparentclass:获取父类的reflectionclass实例。

在反射中,类、接口、特性不分家,所以reflectionclass提供类型判定api:isinterfaceistrait

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

getdoccomment:获取类的文档注释信息;getfilename:获取类定义的文件;getstartline: 获取类定义的起始行号;getendline:循序渐进造句 获取类定义的结束行号;getmodifiers:获取类定义的修饰符,其意义名字可通过reflection::getmodifiernames得到,例如:abstract,final。

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

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

api操作

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

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

设置访问控制权:taccessible。可获取私有的方法/属性。注意:taccessible只是让方法/成员变量可以invoke/getvalue/tvalue,并不代表类定义的访问存取权限改变;调用函数/方法:invoke/invokeargs。配合获取函数参数的api,可以安全的传参和调用函数,call_ur_func(_array)的增强版;不依赖构造函数生成实例:newinstancewithoutconstructor

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

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

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

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

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

对比

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

功能函数式api反射api函数是否存在function_existsreflectionfunction类是否存在class_exitsreflectionclass方法是否存在method_exitsreflectionmethod变量/属性是否存在property_exitsreflectionproperty获取类变量get_class_varsreflectionclass::getproperties获取类方法get_class_methodsreflectionclass::getmethods获取类常量—reflectionclass::regetreflectionconstant(s)获取函数/方法参数信息—reflectionfunction/method::getparameters获取函数/方法返回值—reflectionfunction/method::getreturntype类使用的特性class_usreflectionclass::gettraits获取父类class_parentsreflectionclass::getparentclass获取类实现的接口class_implementsreflectionclass::getinterfacenames获取类所在名字空间__namespace__reflectionclass::getnamespacename函数调用call_ur_func(_array)reflectionmethod(function)::invoke(args)获取类名__class__/::classreflectionclass::getname获取函数名__method__/__function__reflectionfunction/method::getname获取类/常量/变量/方法修饰符—reflectionclass/constant/property/method::getmodifiers获取所在文件__file__reflectionclass/constant/function/method::getfilename获取所在行(范围)—reflectionclass/function/method::getstartline/getendline获取文档—reflectionclass/function/method::getdoccommentextension_loadedreflectionzendextension拓展get_loaded_extensionsreflectionextensionge泪水作文t_extension_funcs

从上表可以看出反射api较函数式api能提供更全面的信息。还需要注意到__fi清明节的介绍le__这类魔术常量是编译期的工作,不是运行时的能力。

同时给出rt雾里看花歌词ti的函数式api和反射api在功能上的差异:

功能函数式api反射api类型判断is_int/is_bool/is_array等—获取对象的类名get_classreflectionobject::getname获取对象父类get_parent_classreflectionobject::getparentclass类型/继承检测instanceof/is_a/is_subclass_ofreflectionobject::isinstance/issubclassof生成器—reflectiongenerator

总结

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

感谢阅读,欢迎指正!

以上就是php反射知识回顾的详细内容,更多关于php 反射的资料请关注www.887551.com其它相关文章!

本文发布于:2023-04-08 23:41:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/60553263e03575936e5ad1750192369e.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:PHP反射基础知识回顾.doc

本文 PDF 下载地址:PHP反射基础知识回顾.pdf

标签:反射   函数   代码   定义
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图