php 反射API

<?php

class Person{
	public $name;
	function __construct($name){
		$this->name = $name;
	}
}

interface Module{
	function execute();
}

class FtpModule implements Module{
	private $host;
	private $user; 

	function setHost($host){
		$this->host = $host;
		echo "FtpModule::setHost() : {$this->host} <br/>";
	}

	function setUser($user){
		$this->user = $user;
		echo "FtpModule::setUser() : {$this->user} <br/>";
	}

	function execute(){
		//执行一些操作
		echo "Host: {$this->host} & User: {$this->user} <br/>";
	}
}

class PersonModule implements Module{
	private $name;

	function setPerson( Person $person ){
		$this->name = $person->name;
		echo "PersonModule::setPerson() :  {$person->name} <br/>";
	}

	function execute(){
		//执行一些操作
		echo "Name: {$this->name}<br />";
	}
}

class ModuleRunner{
	private $configData = array(
			"PersonModule" => array('person'=>'leokim'),
			"FtpModule" => array('host'=>'www.leokim.cn','user'=>'leokim')
		);

	private $modules = array();

	function init(){
		$interface = new ReflectionClass('Module');

		foreach($this->configData as $modulename => $params){
			$module_class = new ReflectionClass($modulename);

			if( !$module_class->isSubclassOf($interface)){
				throw new Exception("unknow module type:$modulename");
			}
			$module = $module_class->newInstance();

			foreach($module_class->getMethods() as $method){
				//module,module内的方法,方法的参数
				$this->handleMethod($module, $method, $params);
			}
			array_push($this->modules, $module);
		}
	}

	//handleMethod()检验并调用Module对象的setter方法
	function handleMethod(Module $module, ReflectionMethod $method, $params){
		$name = $method->getName();
		//所需要的参数
		$args = $method->getParameters();
		
		if(count($args) != 1 || substr($name, 0, 3) != "set"){
			return false;
		}

		$property = strtolower(substr($name, 3));
		if(!isset($params[$property])){
			return false;
		}

		print_r($args[0]);
		echo ' | ';

		//ReflectionMethod::invoke()。它以一个对象和任意数目的方法作为参数
		//可以通过两种途径调用invoke()方法:
		//1.如果setter方法不需要对象参数,可以用用户提供的属性字符串来调用ReflectionMethod::invoke()。
		//2.如果方法需要对象作为参数,可以使用属性字符串来实例化正确类型的对象,然后传递给setter。
		//这个例子里 Person是有Class的 所以在else里执行,Ftp并没有Class所以在if里执行
		$arg_class = $args[0]->getClass();

		if(empty($arg_class)){
			$method->invoke($module, $params[$property]);
		}else{
			$method->invoke($module, $arg_class->newInstance($params[$property]));
		}

		//执行固有的function execure()
		$module->execute();

	}
}


//在ModuleRunner::init()方法运行时,ModuleRunner对象存储着许多Module对象,而所有Module对象都包含着数据。
//ModuleRunner类现在可以用一个类方法来循环遍历没个Module对象,并逐一调用各Module对象中的excute()方法
$test = new ModuleRunner();
$test->init();

?>