zoukankan      html  css  js  c++  java
  • PHP使用反射动态加载第三方类

    • 用反射加载第三方类用处在于:
    1. 使用XML或其他配文件配置要加载的类,从而和系统源代码分离
    2. 对加载的类进行类检查,是加载的类符合自己定义的结构
      1 <?php
      2     abstract class Module {    #核心Module类库
      3         function baseFunc() {
      4             echo "I am baseFunc";
      5         }
      6         
      7         abstract function execute();
      8     }
      9     
     10     class ModuleRunner {
     11         private $configData = array(    #模拟xml配置,动态配置需要加载的Module
     12             "PersonModule" => array("person" => "bob"),
     13             "FtpModule" => array("host" => "example.com", "user" => "anon")
     14         );
     15         
     16         private $modules = array();
     17         
     18         function init() {    #初始化ModuleRunner,加载配置中的Module
     19             $parent = new ReflectionClass("Module");
     20             foreach($this->configData as $moduleName => $params) {    #检查配置中的Module是否合法
     21                 $moduleClass = new ReflectionClass($moduleName);
     22                 if(! $moduleClass->isSubclassOf($parent)) {    #检查是否是Module的子类型
     23                     throw new Exception("unknown type : {$moduleName}");
     24                 }
     25                 $module = $moduleClass->newInstance();
     26                 foreach($moduleClass->getMethods() as $method) {    #检查配置中的函数的参数格式是否正确
     27                     $this->handleMothod($module, $method, $params);
     28                 }
     29                 array_push($this->modules, $module);    #加载Module
     30             }
     31         }
     32         
     33         private function handleMothod(Module $module, ReflectionMethod $method, $params) {    #检查Module中的方法参数是否和传入的$params名字相同,并且具有set方法
     34             $name = $method->getName();
     35             $args = $method->getParameters();
     36         
     37             if(count($args) != 1 || substr($name, 0, 3) != "set") {    #如果没有配置中的类的方法的参数个数不为1,或者方法名前3个字母不为set,返回false
     38                 return false;
     39             }
     40             
     41             $property = strtolower(substr($name, 3));
     42             if(!isset($params[$property])) {    #如果方法名后三个字母与配置中的参数名不同,返回false
     43                 return false;
     44             }
     45             
     46             $argClass = $args[0]->getClass();    #获取参数的类型
     47             if(empty($argClass)) {
     48                 $method->invoke($module, $params[$property]);    #参数无类型限制则直接调用set方法
     49             } else {
     50                 $method->invoke($module, $argClass->newInstance($params[$property]));    #有类型限制则新建一个实例并调用set方法
     51             }
     52         }
     53         
     54         public function getModules() {
     55             return $this->modules;
     56         }
     57     }
     58     
     59     class Person {    #第三方类
     60         public $name;
     61         
     62         function __construct($name) {
     63             $this->name = $name;
     64         }
     65     }
     66     
     67     class FtpModule extends Module {    #用户自定义第三方Module
     68         private $host = "default host";
     69         private $user = "default user";
     70         
     71         function setHost($host) {
     72             $this->host = $host;
     73         }
     74         
     75         function setUser($user) {
     76             $this->user = $user;
     77         }
     78         
     79         function execute() {
     80             echo "{$this->user} user {$this->host}";
     81         }
     82     }
     83     
     84     class PersonModule extends Module {    #用户自定义第三方Module
     85         private $person;
     86     
     87         function setPerson(Person $person) {
     88             $this->person = $person;
     89         }
     90         
     91         function execute() {
     92             if(isset($person)) {
     93                 echo "I am {$this->person->name}";
     94             } else {
     95                 echo "I am no user";
     96             }
     97         }
     98     }
     99     
    100     $modRunner = new ModuleRunner();
    101     $modRunner->init();
    102     var_dump($modRunner);
    103 ?>

    输出

    object(ModuleRunner)#1 (2) { ["configData":"ModuleRunner":private]=> array(2) { ["PersonModule"]=> array(1) { ["person"]=> string(3) "bob" } ["FtpModule"]=> array(2) { ["host"]=> string(11) "example.com" ["user"]=> string(4) "anon" } } ["modules":"ModuleRunner":private]=> array(2) { [0]=> object(PersonModule)#4 (1) { ["person":"PersonModule":private]=> object(Person)#10 (1) { ["name"]=> string(3) "bob" } } [1]=> object(FtpModule)#3 (2) { ["host":"FtpModule":private]=> string(11) "example.com" ["user":"FtpModule":private]=> string(4) "anon" } } }

  • 相关阅读:
    锐捷交换机密码恢复
    adobe cs3系列产品官方帮助网页(中文)
    网页设计视频教程
    锐捷交换机、路由器配置手册
    WINPE下如何直接删除联想隐藏分区?
    IWMS实现频道页面的方法
    SATA、SCSI、SAS区别与特点
    自定义系统必备
    自己写的Web服务器
    尝试MVP模式
  • 原文地址:https://www.cnblogs.com/zemliu/p/2531502.html
Copyright © 2011-2022 走看看