简单聊聊PHP中的反射(Reflection)

简单聊聊PHP中的反射

和Java一样PHP中也提供了一套完整的反射API,何为反射?以前我们是先写类,再在类中添加各种方法和属性,最后实例化一个类对象调用属性和方法。那有我们没有办法只通过这个实例对象获取到关于这个类的全部信息呢,包括有哪些方法和属性它们分别在多少行?答案就是反射

几个常用的反射API的类
类名 作用
Reflection 为类提供摘要信息
ReflectionClass 对类提供反射
ReflectionMethod 对方法提供反射
ReflectionParameter 对方法参数提供反射
ReflectionProperty 对类属性提供反射
ReflectionFunction 对函数提供反射
ReflectionExtension 对扩展提供反射
ReflectionException 对异常提供反射

ReflectionClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class People {
protected $name = 'Foo';
protected $age = 18;

public function __construct($name,$age)
{
$this->name = $name;
$this->age = $age;
}

public function toString()
{
echo "Name: $this->name, Age: $this->age" . PHP_EOL;
}
}

class Student extends People {
public $major;

public function __construct($name, $age, $major)
{
$this->major = $major;
parent::__construct($name, $age);
}

public function toString()
{
echo "Name: $this->name, Age: $this->age, Major: $this->major" . PHP_EOL;
}
}

$reflect = new ReflectionClass('Student');
Reflection::export($reflect);

输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Class [ <user> class Student extends People ] {
@@ /…/demo1.php 18-31

- Constants [0] {
}

- Static properties [0] {
}

- Static methods [0] {
}

- Properties [3] {
Property [ <default> public $major ]
Property [ <default> protected $name ]
Property [ <default> protected $age ]
}

- Methods [2] {
Method [ <user, overwrites People, ctor> public method __construct ] {
@@ /…/demo1.php 21 - 25

- Parameters [3] {
Parameter #0 [ <required> $name ]
Parameter #1 [ <required> $age ]
Parameter #2 [ <required> $major ]
}
}

Method [ <user, overwrites People, prototype People> public method toString ] {
@@ /…/demo1.php 27 - 30
}
}
}

可以看到,Reflection::export几乎提供了Student类的所以信息,包括属性和方法的访问控制状态,每个方法需要的参数以及每个方法在脚本中的位置,和var_dump相比,在使用var_dump前总是需要实例化一个对象,而且无法提供那么多详细信息。

var_dump输出如下:

1
2
3
4
5
6
7
8
object(Student)#1 (3) {
["major"]=>
string(2) "CS"
["name":protected]=>
string(5) "Jason"
["age":protected]=>
int(21)
}

虽然var_dumpprint_r是打印数据的利器,但对于类和函数,反射API提供了更高层次的功能。