拓展PHP反射机制的使用方式

作者: 乘风御上者 分类: PHP 发布时间: 2020-07-30 13:30

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 {
	// 内部属性及方法同上	
}

// 其他后续操作的类,可直接参考手册。

需要注意部分方法返回的结果是对象或数组对象,且都是与反射相关的对象,可参阅手册进行下一步操作。

仔细阅读一下反射的方法就会明白,反射对类的操作几乎涵盖方方面面。 正常可以对类进行的操作,通过反射同样能实现。

如此我们就可以进行各种骚操作。哦,是各种优雅的操作。当然使用要有度,不要破坏了类的封装性(因反射可轻易获得私有及保护属性和方法等)。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表回复