当前位置:首页 > 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.   
  26. class Person {  #第三方类 
  27.   public $name; 
  28.     
  29.   function __construct($name) { 
  30.     $this->name = $name; 
  31.   } 
  32. } 
  33.   
  34. class FtpModule extends Module {  #用户自定义第三方Module 
  35.   private $host = "default host"; 
  36.   private $user = "default user"; 
  37.     
  38.   function setHost($host) { 
  39.     $this->host = $host; 
  40.   } 
  41.     
  42.   function setUser($user) { 
  43.     $this->user = $user; 
  44.   } 
  45.     
  46.   function execute() { 
  47.     echo "{$this->user} user {$this->host}"; 
  48.   } 
  49. } 
  50.   
  51. class PersonModule extends Module {  #用户自定义第三方Module 
  52.   private $person; 
  53.   
  54.   function setPerson(Person $person) { 
  55.     $this->person = $person; 
  56.   } 
  57.     
  58.   function execute() { 
  59.     if(isset($person)) { 
  60.       echo "I am {$this->person->name}"; 
  61.     } else { 
  62.       echo "I am no user"; 
  63.     } 
  64.   } 
  65. } 
  66.   
  67. $modRunner = new ModuleRunner(); 
  68. $modRunner->init(); 
  69. 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加载源码

分享到: