拓展PHP反射机制的使用方式
PHP的反射功能日常用的非常少,目前只在各种PHP框架的实现上用到。 反射的概念也很好理解,用法也非常简单。但在使用时比较灵活,能实现各种天马行空的想法。
反射指PHP在运行时,能动态的提取关于类的所有信息,包括类的方法、属性、方法与属性的权限、参数、注释等详细信息。
用法有两种,一种是通过类名入手分析,一种是通过类的实例化对象入手分析:
// 通过类名分析
$reflect = new ReflectionClass(类名);
// 通过对象分析
$reflect = new ReflectionObject(对象);
以上两种方式都将得到 ReflectionClass 类的实例化对象( ReflectionObject 继承自 ReflectionClass ,所有方法调用方式完全一致)。
// 只作为反射的约定接口使用,并无其他功能
Reflector {
public static export ( void ) : string
public __toString ( void ) : string
}
// 上面分析类得到的$reflect可使用方法列表
// 需要注意下列方法的返回值类型,部分方法返回的是对象,根据不同对象(参考反射手册其他类)继续操作
ReflectionClass implements Reflector {
// 获取被分析者的类名
public $name;
// 获取被分析者的类名
public getName ( void ) : string
// 获取被分析者名称,除命名空间的部分
public getShortName ( void ) : string
// 获取被分析者的命名空间名称
public getNamespaceName ( void ) : string
// 获取被分析者的父类(对象形式)
public getParentClass ( void ) : ReflectionClass
// 获取被分析者的构造方法
public getConstructor ( void ) : ReflectionMethod
// 获取被分析者的类注释信息
public getDocComment ( void ) : string
// 获取被分析者指定名称的常量
public getConstant ( string $name ) : mixed
// 获取被分析者所有的常量(不管是私有还是保护都将返回)
public getConstants ( void ) : array
// 获取被分析者指定名称的常量(对象形式)
public getReflectionConstant ( string $name ) : ReflectionClassConstant
// 获取被分析者所有的常量(对象形式)
public getReflectionConstants ( void ) : array
// 获取被分析者所有的属性(对象形式)
// 可选择获取哪种类型的属性
public getProperties ([ int $filter ] ) : array
// 获取被分析者指定名称的属性
public getProperty ( string $name ) : ReflectionProperty
// 获取被分析者所有的属性值,包括继承属性以及静态与非静态、私有、受保护、公开的
public getDefaultProperties ( void ) : array
// 获取被分析者所有的静态属性
public getStaticProperties ( void ) : array
// 获取被分析者指定名称的静态属性的值
public getStaticPropertyValue ( string $name [, mixed &$def_value ] ) : mixed
// 设置被分析者指定静态属性的值
public setStaticPropertyValue ( string $name , string $value ) : void
// 获取被分析者指定名称的方法(对象形式)
public getMethod ( string $name ) : ReflectionMethod
// 获取被分析者所有的方法(对象形式)
// 可选择获取哪种类型的方法
public getMethods ([ int $filter ] ) : array
// 获取被分析者所在文件的文件名
public getFileName ( void ) : string
// 获取被分析者所在文件定义时的开始行号
public getStartLine ( void ) : int
// 获取被分析者所在文件定义时的最后一行行号
public getEndLine ( void ) : int
// 获取被分析者所在扩展对象信息
public getExtension ( void ) : ReflectionExtension
// 获取被分析者所在扩展的名称
public getExtensionName ( void ) : string
// 导出被分析者
public static export ( mixed $argument [, bool $return = false ] ) : string
// 获取被分析者继承实现的所有接口类名称
public getInterfaceNames ( void ) : array
// 获取被分析者继承实现的所有接口类,不同于上例该返回数组元素是ReflectionClass对象
public getInterfaces ( void ) : array
// 获取被分析者的修饰符
public getModifiers ( void ) : int
// 获取被分析者继承的所有trait对象的数组(元素是ReflectionClass对象形式)
public getTraits ( void ) : array
// 获取被分析者继承的所有trait别名数组
public getTraitAliases ( void ) : array
// 获取被分析者继承的所有trait的名称数组
public getTraitNames ( void ) : array
// 检测被分析者指定的常量是否定义
public hasConstant ( string $name ) : bool
// 检测被分析者指定的方法是否定义
public hasMethod ( string $name ) : bool
// 检测被分析者指定的属性是否定义
public hasProperty ( string $name ) : bool
// 检测被分析者是否实现了指定的接口
public implementsInterface ( string $interface ) : bool
// 检测被分析者是否在指定的命名空间下
public inNamespace ( void ) : bool
// 检测被分析者是否是抽象类
public isAbstract ( void ) : bool
// 检测被分析者是否是匿名类
public isAnonymous ( void ) : bool
// 检测被分析者是否可复制
public isCloneable ( void ) : bool
// 检测被分析者是否是终极类
public isFinal ( void ) : bool
// 检测被分析者是否为指定类的实例
public isInstance ( object $object ) : bool
// 检测被分析者是否可以实例化
public isInstantiable ( void ) : bool
// 检测被分析者是否是接口类
public isInterface ( void ) : bool
// 检测被分析者是否由扩展或核心在内部定义
public isInternal ( void ) : bool
// 检测被分析者是否可以被迭代
public isIterable ( void ) : bool
// 检测被分析者是否可以被迭代(通过实例没发现与上面的不同点)
public isIterateable ( void ) : bool
// 检测被分析者是否是指定类的子类
public isSubclassOf ( string $class ) : bool
// 检测被分析者是否是trait
public isTrait ( void ) : bool
// 检测被分析者是否是用户定义的类
public isUserDefined ( void ) : bool
// 为被分析者创建新的实例
public newInstance ( mixed $args [, mixed $... ] ) : object
// 为被分析者创建新的实例(与上例不同点在于传递给实例的参数形式)
public newInstanceArgs ([ array $args ] ) : object
// 为被分析者创建新的实例,但不调用其构造函数。若创建过程报错则抛出ReflectionException异常
public newInstanceWithoutConstructor ( void ) : object
}
ReflectionObject extends ReflectionClass {
// 内部属性及方法同上
}
// 其他后续操作的类,可直接参考手册。
需要注意部分方法返回的结果是对象或数组对象,且都是与反射相关的对象,可参阅手册进行下一步操作。
仔细阅读一下反射的方法就会明白,反射对类的操作几乎涵盖方方面面。 正常可以对类进行的操作,通过反射同样能实现。
如此我们就可以进行各种骚操作。哦,是各种优雅的操作。当然使用要有度,不要破坏了类的封装性(因反射可轻易获得私有及保护属性和方法等)。