PHP具有完整的反射API,可以对类、接口、函数、方法和扩展进行反向工程。反射API并提供方法取出函数、类和方法中的文档注释
简单来说, 给定一个类名, 可以提取到这个类的所有信息, 可以构建自动化文档, 可以通过分析参数来实现依赖注入
官方文档
总文档: https://www.php.net/manual/zh/book.reflection.php类反射
: https://www.php.net/manual/zh/class.reflectionclass.php
反射api的一些类
ReflectionClass
类信息和工具操作ReflectionMethod
类方法和工具操作ReflectionParameter
方法参数反射ReflectionProperty
类属性反射ReflectionFunction
函数反射ReflectionExtension
扩展信息ReflectionException
错误信息
类反射
要分析的类
namespace reflection;
/**
* Class A
*/
class A {
public $f1 = 1;
protected $f2 = 2;
private $f3 = 3;
public function Foo()
{
}
}
interface Abc {
}
/**
* Class B
* this is class Doc
*/
class B extends A implements Abc{
const TEST_1 = 1;
const TEST_2 = 2;
public $prop1 = 1;
protected $prop2 = 2;
private $prop3 = 3;
public static $prop_static = [1];
public function __construct()
{
}
public function foo1(int $a, int $b)
{
}
public function foo2(int $a, string $b)
{
}
protected function foo3()
{
}
private function foo4()
{
}
}
$obj = new B();
反射api
//$ref = new ReflectionClass($obj);
$ref = new \ReflectionClass(B::class);
//print_r(ReflectionClass::export(demo::class));
print_r($ref->getProperties()); // 获取一级属性, 可以传参数过滤, 返回ReflectionProperty 对象的数组。
var_dump($ref->getConstructor()); // 获取构造函数, 未定义返回null
var_dump($ref->inNamespace()); // 是否在命名空间中
var_dump($ref->getConstants()); // 获取所有定义的常量
var_dump($ref->getConstant('TEST_1')); // 获取某个常量
print_r($ref->getDefaultProperties()); // 获取默认属性, 返回数组, 包括父类的属性
var_dump($ref->getDocComment()); // 获取类文档注释, 不包含属性和方法的注释, 无注释返回false
var_dump($ref->getExtension()); // 获取获取最后一行的行数
var_dump($ref->getFileName()); // 获取定义类的文件名, 返回绝对路径
var_dump($ref->getInterfaceNames()); // 获取接口名称, 返回索引数组,值为接口名称, 未实现接口返回空数组
var_dump($ref->getInterfaces()); // 获取接口, 返回关联数组, name=>ReflectionClass实例, 未实现接口返回空数组
var_dump($ref->getMethods()); // 指获取类方法 ReflectionMethod。
var_dump($ref->getMethod('foo4')); // 获取一个类方法的 ReflectionMethod。如果方法不存在会抛出异常, 需要配合try catch一起用
var_dump($ref->getName()); // 获取类名, 包含命名空间
var_dump($ref->getNamespaceName()); // 获取命名空间的名称, 没有返回空
var_dump($ref->getParentClass()); // 获取父类reflectionClass的实例, 没有父类返回false
var_dump($ref->getProperty('prop3')); // 获取一个属性, 返回ReflectionProperty实例, 属性不存在会抛出异常, 需配合try catch使用
var_dump($ref->getShortName()); // 获取类名, 不包含命名空间
var_dump($ref->getStartLine()); // 获取起始行号
print_r($ref->getStaticProperties()); // 获取静态属性
print_r($ref->getStaticPropertyValue('prop_static')); // 获取静态属性值, 未定义的属性会报致命错误
print_r($ref->getTraitAliases()); // 返回 trait 别名的一个数组
print_r($ref->getTraitNames()); // 返回 trait 别名的一个数组
print_r($ref->getTraits()); // 返回这个类所使用的 traits 数组
var_dump($ref->hasConstant('AB')); // 检查常量是否已经定义
var_dump($ref->hasMethod('AB')); // 检查方法是否已经定义
var_dump($ref->hasProperty('AB')); // 检查属性是否已定义
var_dump($ref->implementsInterface('reflection\Abc')); // 检查是否实现了某个接口, 注意需要带上命名空间
var_dump($ref->isAbstract()); // 检查类是否是抽象类(abstract)
var_dump($ref->isAnonymous()); // 检查类是否是匿名类
var_dump($ref->isCloneable()); // 返回了一个类是否可复制
var_dump($ref->isFinal()); // 检查类是否声明为 final
var_dump($ref->isInstance($obj)); // 检查一个变量是否此类的实例
var_dump($ref->isInstantiable()); // 检查类是否可实例化
var_dump($ref->isInterface()); // 检查类是否是一个接口(interface)
var_dump($ref->isInternal()); // 检查类是否由扩展或核心在内部定义, 和isUserDefined相对
var_dump($ref->isIterateable()); // 检查此类是否可迭代, 实现了Iterator接口即可迭代
var_dump($ref->isSubclassOf(A::class)); // 是否是某一个类的子类
var_dump($ref->isTrait()); // 返回了是否为一个 trait
var_dump($ref->isUserDefined()); // 检查是否由用户定义的类 和isInternal相对
// 从指定的参数创建一个新的类实例,创建类的新的实例。给出的参数将会传递到类的构造函数。
// 接受可变数目的参数,用于传递到类的构造函数,和 call_user_func() 很相似。
var_dump($ref->newInstance());
// 从指定的参数创建一个新的类实例,创建类的新的实例。给出的参数将会传递到类的构造函数。
//这个参数以 array 形式传递到类的构造函数。
var_dump($ref->newInstanceArgs([]));
var_dump($ref->newInstanceWithoutConstructor()); // 创建一个新的实例而不调用他的构造函数
$ref->setStaticPropertyValue ('prop_static', '222'); // 设置静态属性的值, 无返回值
var_dump($ref->__toString ()); // 返回 ReflectionClass 对象字符串的表示形式。