当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP通过反射动态加载第三方类和获得类源码的实例

发布:smiling 来源: PHP粉丝网  添加日期:2021-06-27 13:32:20 浏览: 评论:0 

这篇文章主要介绍了PHP通过反射动态加载第三方类和获得类源码的方法,一般在解析XML文件时会用到,需要的朋友可以参考下。

使用反射动态加载第三方类

用反射加载第三方类用处在于:

使用XML或其他配文件配置要加载的类,从而和系统源代码分离,对加载的类进行类检查,是加载的类符合自己定义的结构。

  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.     } 

private function handleMothod(Module $module, ReflectionMethod $method, $params) {  #检查Module中的方法参数是否和传入的$params名字相同,并且具有set方法。

  1.    $name = $method->getName(); 
  2.     $args = $method->getParameters(); 
  3.     
  4.     if(count($args) != 1 || substr($name, 0, 3) != "set") {  #如果没有配置中的类的方法的参数个数不为1,或者方法名前3个字母不为set,返回false 
  5.       return false; 
  6.     } 
  7.       
  8.     $property = strtolower(substr($name, 3)); 
  9.     if(!isset($params[$property])) {  #如果方法名后三个字母与配置中的参数名不同,返回false 
  10.       return false; 
  11.     } 
  12.       
  13.     $argClass = $args[0]->getClass();  #获取参数的类型 
  14.     if(emptyempty($argClass)) { 
  15.       $method->invoke($module$params[$property]);  #参数无类型限制则直接调用set方法 
  16.     } else { 
  17.       $method->invoke($module$argClass->newInstance($params[$property]));  #有类型限制则新建一个实例并调用set方法 
  18.     } 
  19.   } 
  20.     
  21.   public function getModules() { 
  22.     return $this->modules; 
  23.   } 
  24.   
  25. class Person {  #第三方类 
  26.   public $name
  27.     
  28.   function __construct($name) { 
  29.     $this->name = $name
  30.   } 
  31.   
  32. class FtpModule extends Module {  #用户自定义第三方Module 
  33.   private $host = "default host"
  34.   private $user = "default user"
  35.     
  36.   function setHost($host) { 
  37.     $this->host = $host
  38.   } 
  39.     
  40.   function setUser($user) { 
  41.     $this->user = $user
  42.   } 
  43.     
  44.   function execute() { 
  45.     echo "{$this->user} user {$this->host}"
  46.   } 
  47.   
  48. class PersonModule extends Module {  #用户自定义第三方Module 
  49.   private $person
  50.   
  51.   function setPerson(Person $person) { 
  52.     $this->person = $person
  53.   } 
  54.     
  55.   function execute() { 
  56.     if(isset($person)) { 
  57.       echo "I am {$this->person->name}"
  58.     } else { 
  59.       echo "I am no user"
  60.     } 
  61.   } 
  62.   
  63. $modRunner = new ModuleRunner(); 
  64. $modRunner->init(); 
  65. var_dump($modRunner); 

输出:

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" } } }

通过反射获得类源码:

  1. <?php 
  2.   function getSource(ReflectionClass $ref) { 
  3.     $path = $ref->getFileName();  #获取脚本文件文件名 
  4.     $file = file($path); #file()方法获取文件内容,并将内容保存在一个数组中,数组每个元素保存一行内容 
  5.     $start = $ref->getStartLine();  #获取类在脚本中的第一行行号 
  6.     $end = $ref->getEndLine();  #获取类在脚本中最后一行的行号 
  7.     $source = implode(array_slice($file$start - 1, $end - $start + 1));  #拼装类源码 
  8.       
  9.     var_dump($source); 
  10.   } 
  11.  
  12.   class Person { 
  13.     public $age
  14.     private $name
  15.       
  16.     function say() { 
  17.       echo "yes"
  18.     } 
  19.   } 
  20.     
  21.   $ref = new ReflectionClass("Person"); 
  22.   getSource($ref); 
  23. ?>

Tags: PHP反射动态 PHP加载源码

分享到: