用php反射实现插件的自动调用
<?php //接口组件 interface Module { public function excute(); }
<?php //ftp类 class FtpModule implements Module { public function setHost($host) { print "FtpModule::setHost():$host <br />"; } public function setUser($user) { print "FtpModule::setUser():$user <br />"; } public function excute() { } }
<?php //person类 class PersonModule implements Module { public function setPerson($person) { print "PersonModule::setPerson $person <br />"; } public function excute() { } }
<?php class ModuleRunner { private $configData = array( 'PersonModule'=>array('person'=>'bbb'), 'FtpModule'=>array('host'=>'example.com','user'=>'anon') ); private $modules = array(); /** * init 初始化方法 * 循环遍历ModuleRunner::$configData数组 它尝试为每个模块元素创建Reflec-tionClass对象 * 。如果是不存在的类名调用ReflectionClass 会抛出异常 所以在真实情况下 我们应该在这里写更多的错误验证 * 使用ReflectionClass::isSubclassOf方法确定模块属于Module接口 */ public function init() { $interface = new ReflectionClass('Module');//反射接口 foreach($this->configData as $modulename => $params) { //循环实例反射类 $module_class = new ReflectionClass($modulename); if(!$module_class->isSubclassOf($interface)) { //判断是不是Module接口的实例 throw new Exception("unknown module type:$modulename"); } $module = $module_class->newInstance(); //实例化一个类 接受任意多的参数 这些参数传到相应的构造方法里面 如果一切正确 返回类的实例 foreach($module_class->getMethods() as $method) { //遍历所有的方法 $this->handleMethod($module,$method,$params); //调用方法 :类本身 方法名 传参 } array_push($this->modules,$module); //添加到modules数组里面 } } //调用方法 public function handleMethod(Module $module ,ReflectionMethod $method, $params) { $name = $method->getName(); //获取方法名称 $args = $method->getParameters(); //获取函数参数 if(count($args)!= 1 || substr($name,0,3) != 'set') { //判断是不是set方法 return false; } $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])); //是就执行对象 } } }
<?php require "Module.class.php"; require "FtpModule.class.php"; require "PersonModule.class.php"; require "person.class.php"; require "ModuleRunner.class.php"; $a = new ModuleRunner(); try { $a->init(); }catch(Exception $e) { exit($e->getMessage()); }