您的位置:首页 > 编程语言 > PHP开发

PHP反射API实现自动加载

2016-09-07 14:20 801 查看
PHP具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 在这里我们通过一个简单的应用来展示一下反射API的魅力。

让我们来看看如何利用反射api实现自动加载模块

首先定义一个modules接口,不同模块实现不同的execute()功能。

interface modules{
function execute();
}


接下来定义我们在这个例子中要用到的模块(要求:每个模块中都要有set+属性字符串 方法来完成模块参数的设置,而且该方法有且仅有一个参数,支持对象参数和字符串参数)。

//邮箱模块
class mailModule implements modules
{
//邮箱地址
public $address;
//设置地址方法
public function setAddress($address)
{
$this->address=$address;
}
//     模块功能,开启邮箱服务
public function execute()
{
echo "mail start<br>";
}
}
// userModule的依赖类
class user
{
public $username;
public function __construct($name)
{
$this->username=$name;
}
}
//用户配置模块
class userModule implements modules
{
public $user;
public function setUser(user $user)
{
$this->user=$user;
}
public function execute()
{
//显示当前用户
echo "current user is {$this->user->username}<br>";
}
}


好了,定义好我们要用到的模块后,接下来定义自动加载模块类。

class autoLoadModule{
//配置数组
private $configArray=array(
'mailModule'=>array(
'address'=>'1151864810@qq.com',
),
'userModule'=>array(
'user'=>'manyhong',
),
);
//模块列表
public $moduleList=array();
//模块初始化方法,本质是调用所有模块的初始化相关函数
public function init()
{
foreach ($this->configArray as $moduleName => $config) {
//实例化一个关联到模块类的reflectionClass对象
$moduleClass = new ReflectionClass($moduleName);
//判断模块是否存在
if (!$moduleClass->isSubclassOf('modules')) {
throw new Exception("module:$moduleName doesn't exist");
}
//实例化模块对象
$module = $moduleClass->newInstance();
//得到一组对应模块类的reflectionMethod对象
$methods=$moduleClass->getMethods();
//遍历模块中的所有方法
foreach ($methods as $method){
//InitEngine初始化核心引擎,需要传入模块对象和reflectionMethod对象和相关配置文件
$this->InitEngine($module,$method,$config);
}
$this->moduleList[]=$module;
}
}


初始化核心引擎:

public function InitEngine(modules $module,ReflectionMethod $method,$moduleConfigs){
//获取方法名
$methodName=$method->getName();
//获取方法的参数列表
$args=$method->getParameters();
//过滤出符合系统要求的模块初始化方法:命名规则setXXX,参数有且只有一个
if(substr($methodName,0,3)!= 'set' || count($args)!=1){
return false;
}
//从方法名中获取需要初始化的属性(所以上文我们才对设置属性方法的命名有要求)
$property=strtolower(substr($methodName,3));
//如果配置文件中该配置项为空则直接返回false
if(is_null($moduleConfigs[$property])){
return false;
}
//如果配置项不为空,接着判断参数类型,决定是否需要实例化依赖类
//调用reflectionParameter::getClass方法()获取参数类型
$parameterType=$args[0]->getClass();
//如果是字符串类型
if(is_null($parameterType)){
//调用reflectionMethod::invoke方法,传入方法所在对象和方法实参
$method->invoke($module,$moduleConfigs[$property]);
return true;
}else{
/*如果是对象类型,则需要初始化依赖类对象后再传入*/                                                   $method->invoke($module,new$property($moduleConfigs[$property]));
return true;
}
}
//调用所有模块功能
public function run(){
foreach ($this->moduleList as $module){
$module->execute();
}
}
}


最后我们就可以在客户端中来使用,代码如下:

//实例化这个自动加载类对象
$obj=new autoLoadModule();
//自动加载模块并根据配置完成模块初始化工作
$obj->init();
//然后就可以使用模块了
$obj->run();


反射不仅可以应用在自动加载第三方控件上,还可以帮助我们获取关于类,方法等的详细信息,也可以帮助我们获取源代码和生成文档,其他使用将博主将在日后补充,今天就先简单让大家感受一下反射API 的用法~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息