反射机制简介
在面向对象编程中,对象被系统赋予了自省的能力,而实现这个自省的过程就是反射。
反射,简单理解就是根据目标物,得到目标物所携带的属性、技能等。在PHP中,我们可以通过反射对象,提取关于类、方法、属性、参数、注释等的详细信息。这种动态获取信息以及动态调用对象方法的功能称为反射API。
反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。比如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。
通过ReflectionClass,我们可以得到某个类的如下信息:
常量 Contants
属性 Property
方法 Method
属性 Static Properties
命名空间 Namespace
类的修饰,是否为final或者abstract
使用
假设我们现在有一个这样的类:
class Student
{
public $name;
protected $age;
private $sex;
public function __construct($name, $age, $sex)
{
$this->setName($name);
$this->setAge($age);
$this->setSex($sex);
}
public function setName($name)
{
$this->name = $name;
}
protected function setAge($age)
{
$this->age = $age;
}
private function setSex($sex)
{
$this->sex = $sex;
}
}
调用反射导出接口:
\ReflectionClass::export(Student::class);
导出结果:
/**
* User: wooylan
* Date: 2019/3/11
* Time: 21:59
*/
Class [ class Student ] {
@@ /path/reflection.php 8-35
- Constants [0] {
}
- Static properties [0] {
}
- Static methods [0] {
}
- Properties [3] {
Property [ public $name ]
Property [ protected $age ]
Property [ private $sex ]
}
- Methods [4] {
Method [ public method __construct ] {
@@ /path/reflection.php 14 - 19
- Parameters [3] {
Parameter #0 [ $name ]
Parameter #1 [ $age ]
Parameter #2 [ $sex ]
}
}
Method [ public method setName ] {
@@ /path/reflection.php 21 - 24
- Parameters [1] {
Parameter #0 [ $name ]
}
}
Method [ protected method setAge ] {
@@ /path/reflection.php 26 - 29
- Parameters [1] {
Parameter #0 [ $age ]
}
}
Method [ private method setSex ] {
@@ /path/test.php 31 - 34
- Parameters [1] {
Parameter #0 [ $sex ]
}
}
}
}
获取对象属性列表
$student = new Student('woodylan', 18, 1);
$reflect = new ReflectionObject($student);
$props = $reflect->getProperties();
foreach ($props as $prop) {
print $prop->getName() . "\n";
}
输出:
name
age
sex
获取对象方法列表
$methods = $reflect->getMethods();
foreach ($methods as $prop) {
print $prop->getName() . "\n";
}
输出:
__construct
setName
setAge
setSex
反射获取类的原型
$reflection = new ReflectionClass(Student::class);
$className = $reflection->getName();
$methods = [];
$properties = [];
foreach ($reflection->getProperties() as $value) {
$properties[$value->getName()] = $value;
}
foreach ($reflection->getMethods() as $value) {
$methods[$value->getName()] = $value;
}
echo "class {$className}\n{\n";
is_array($properties) && ksort($properties);
foreach ($properties as $key => $value) {
echo "\t";
echo $value->isPublic() ? ' public' : '', $value->isPrivate() ? ' private' : '',
$value->isProtected() ? ' protected' : '',
$value->isStatic() ? ' static' : '';
echo "\t{$key}\n";
}
echo "\n";
if (is_array($methods)) ksort($methods);
foreach ($methods as $key => $value) {
echo "\tfunction {$key}(){}\n";
}
echo "}\n";
输出:
class Student
{
protected age
public name
private sex
function __construct(){}
function setAge(){}
function setName(){}
function setSex(){}
}
其它API
反射不仅可以用于类和对象,还可以用于函数、扩展模块、异常等,官方提供了一系列的API方法,以下列举部分。