Dynamic loading of third party classes using reflection
Using reflection to load a third party class is useful:
Use XML or other matching files to configure the classes to be loaded, separating from the system source code.
Class checking of loaded classes is that the loaded class conforms to its own defined structure.
<?php abstract class Module {#核心Module类库 function basefunc () {echo "I am Basefunc";
The abstract function execute (); Class Modulerunner {Private $configData = Array (#模拟xml配置, dynamically configuring the module "Personmodule" => Array ("P") that needs to be loaded
Erson "=>" "Bob"), "Ftpmodule" => Array ("host" => "example.com", "User" => "anon"));
Private $modules = Array ();
function init () {#初始化ModuleRunner, module $parent in the load configuration = new Reflectionclass ("Module"); foreach ($this->configdata as $moduleName => $params) {#检查配置中的Module是否合法 $moduleClass = new Reflectionclass
($moduleName); if (! $moduleClass->issubclassof ($parent)) {#检查是否是Module的子类型 throw new Exception ("unknown type: {$moduleNam
e} ");
$module = $moduleClass->newinstance (); foreach ($moduleClass->getmethods () as $method) {#检查配置中的函数的参数格式是否正确 $this->handlemothod ($module, $method,
$params); } array_push ($this->modules, $module); The #加载Module}} Private Function Handlemothod (Module $module, Reflectionmethod $method, $params) {#检查Mo The method parameters in Dule are
No is the same as the passed-in $params name and has the Set method
$name = $method->getname ();
$args = $method->getparameters (); If Count ($args)!= 1 | | substr ($name, 0, 3)!= "set") {#如果没有配置中的类的方法的参数个数不为1, or the first 3 letters of the method name are not set, returns false return Fals
E
$property = Strtolower (substr ($name, 3));
if (!isset ($params [$property])) {#如果方法名后三个字母与配置中的参数名不同, returns false to false; } $argClass = $args [0]->getclass (); #获取参数的类型 if (empty ($argClass)) {$method->invoke ($module, $params [$property]); #参数无类型限制则直接调用set方法} else {$method->invoke ($module, $argClass->newinstance ($params [$property]));
#有类型限制则新建一个实例并调用set方法}} Public Function GetModules () {return $this->modules;
The class Person {#第三方类 the public $name;
function __construct ($name) {$this->name = $name;
Class Ftpmodule extends Module {#用户自定义第三方Module private $host = "Default Host"; Private $user = "DEfault user ";
function Sethost ($host) {$this->host = $host;
function SetUser ($user) {$this->user = $user;
function execute () {echo "{$this->user} user {$this->host}";
Class Personmodule extends Module {#用户自定义第三方Module private $person;
function Setperson (person $person) {$this->person = $person;
The function execute () {if (Isset ($person)) {echo "I am {$this->person->name}";
else {echo ' I am no user ';
}} $modRunner = new Modulerunner ();
$modRunner->init ();
Var_dump ($modRunner);?>
Output
Object (Modulerunner) #1 (2) {["ConfigData": "Modulerunner":p rivate]=> Array (2) {["Personmodule"]=> Array (1) {] Person "]=> string (3)" Bob "} [" Ftpmodule "]=> Array (2) {[" Host "]=> string (one)" example.com "[" User "]=> string (4) "Anon"} ["Modules": "Modulerunner":p rivate]=> Array (2) {[0]=> object (personmodule) #4 (1) {[Person:] Person Module ":p rivate]=> object (person) #10 (1) {[' Name ']=> string (3) ' Bob '}} [1]=> object (Ftpmodule) #3 (2) {[' Host '] : "Ftpmodule":p rivate]=> string (one) "example.com" ["User": "Ftpmodule":p rivate]=> string (4) "Anon"}}}
Get the class source by reflection
<?php
function GetSource (Reflectionclass $ref) {
$path = $ref->getfilename (); #获取脚本文件文件名
$file = file ($path); #file () method gets the contents of the files and saves the contents in an array, each element of the array holds one row
$start = $ref->getstartline (); #获取类在脚本中的第一行行号
$end = $ref->getendline (); #获取类在脚本中最后一行的行号
$source = Implode (Array_slice ($file, $start-1, $end-$start + 1)); #拼装类源码
var_dump ($source);
}
Class Person {public
$age;
Private $name;
function say () {
echo "yes";
}
}
$ref = new Reflectionclass ("person");
GetSource ($ref);
? >