利用反射API自动加载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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133/**
* User : xiaofan
* Date : 2018/8/29.
*/
class Person
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
interface Module
{
public function execute();
}
class FtpModule implements Module
{
public function setHost($host)
{
echo "FtpModule::setHost() : $host\n".'<br>';
}
public function setUser($user)
{
echo "FtpModule::setUser() : $user\n".'<br>';
}
public function execute()
{
echo 'FtpModule::execute()'.'<br>';
}
}
class PersonModule implements Module
{
public $person;
public function setPerson(Person $person)
{
$this->person = $person;
echo "PersonModule::setPerson() : ( $person->name) \n".'<br>';
}
public function execute()
{
echo 'PersonModule::execute 显示用户:'."{$this->person->name}".'<br>';
}
}
class ModuleRunner
{
private $configData = array(
'PersonModule' => array('person' => 'bob'),
'FtpModule' => array('host' => 'example.com', 'user' => 'tom'),
);
private $modules = array();
public function init()
{
// 创建 Module接口反射类
$interface = new ReflectionClass('Module');
// $modulename : 模块名字 PersonModule FtpModule
// $params : 参数
foreach ($this->configData as $modulename => $params) {
// 创建 模块反射类
$module_class = new ReflectionClass($modulename);
if (!$module_class->isSubclassOf($interface)) {
throw new Exception("未知模块:$modulename");
}
// 实例化 模块类
$module = $module_class->newInstance();
foreach ($module_class->getMethods() as $method) {
$this->handleMethod($module, $method, $params);
}
array_push($this->modules, $module);
}
}
/**
* $module : 模块类实例
* $method :模块方法
* $params :模块参数.
*/
public function handleMethod(Module $module, ReflectionMethod $method, $params)
{
// 方法名
$name = $method->getName();
// 参数 可为空
$args = $method->getParameters();
// 检查方法是否为有效的settter ( set方法必须有参数,前缀是set )
if (count($args) == 0 || substr($name, 0, 3) != 'set') {
return false;
}
// settter方法要设置的属性如方法为setPerson ,则$property为person
$property = strtolower(substr($name, 3));
// 配置中参数是否设置
if (!isset($params[$property])) {
return false;
}
// 尝试实例化参数,用于判断第一个参数类型,是否是对象
$arg_class = $args[0]->getClass();
if (empty($arg_class)) {
$method->invoke($module, $params[$property]);
} else {
// 如果需要 对象作为参数,则实例化对象
$method->invoke($module, $arg_class->newInstance($params[$property]));
}
}
// 调用所有模块功能
public function run()
{
foreach ($this->modules as $module) {
$module->execute();
}
}
}
//实例化这个自动加载类对象
$test = new ModuleRunner();
//自动加载模块并根据配置完成模块初始化工作
$test->init();
//使用模块
$test->run();
输出1
2
3
4
5PersonModule::setPerson() : ( bob)
FtpModule::setHost() : example.com
FtpModule::setUser() : tom
PersonModule::execute 显示用户:bob
FtpModule::execute()