日期:2014-05-17  浏览次数:20442 次

[php]应用控制器(二)

        为了能更清晰地了解应用控制器总体实现的结构,代码中需要使用到的类都已经在之前实现了,现在只剩下的是核心的部分:AppController和Controller。

namespace demo\controller;

/**
 * Controller
 */
class Controller {
	private $appHelper;
	
	// 不能实例化,只能通过Controller::run()的方式来执行
	private function __construct() {
	
	}
	
	public static function run() {
		$instance = new self();
		// 加载配置
		$instance->init();
		// 处理请求
		$instance->handleReuqest();
	}
	
	private function init() {
		$appHelper = \demo\controller\ApplicationHelper::getInstance();
		$appHelper->init();
	}
	
	private function handleReuqest() {
		$request = new \demo\controller\Request();
		$appController = \demo\base\ApplicationRegistry::getInstance()->getAppController();

		// 执行完所有Command,有可能存在forward
		while ($cmd = $appController->getCommand($request)) {
			// var_dump($cmd);
			$cmd->execute($request);
			// 把当前Command设为已执行过
			$request->setLastCommand($cmd);
		}
		// 获取视图
		$view = $appController->getView($request);
		// 显示视图
		$this->invokeView($view);
		
		/* $cmdReslover = new \demo\command\CommandReslover();
		$cmd = $cmdReslover->getCommand($request);
		$cmd->execute($request); */
	}
	
	private function invokeView($view) {
		include("demo/view/{$view}.php");
		exit();
	}
}

        handleRequest()里面的while循环是为了处理<command>中有可能出现的<forward>,<forward>元素的值是对应的Command子类,这些<command>、<forward>、<view>和<status>的关系都已经被映射到ControllerMap中去了。

        Controller执行流程:
        1)读取xml配置到controllerMap对象;
        2)得到$request;
        3)由appController解析$request->getProperty('cmd'),返回$cmd;
        4)$cmd->execute($request),如果controllerMap中存在cmd对应的$forward,则$request->setProperties('cmd', $forward),跳到3),否则跳到5);
        5)由appController->getView($request)取得视图$view;
        6)调用视图invokeView($view);


        应用控制器AppController:

namespace demo\controller;

/**
 * AppController
 */
class AppController {
	private static $baseCmd;
	private static $defaultCmd;
	private $controllerMap;
	// 标记已经执行过的Command,防止出现forward循环
	private $invoked = array();
	
	public function __construct(\demo\controller\ControllerMap $camp) {
		if (!isset(self::$baseCmd)) {
			self::$baseCmd = new \ReflectionClass('\demo\command\Command');
			self::$defaultCmd = new \demo\command\DefaultCommand();
		}
		
		$this->controllerMap = $camp;
	}
	
	public function getView(\demo\controller\Request $request) {
		$view = $this->getResource($request, 'View');
		return $view;
	}
	
	public function getForward(\demo\controller\Request $request) {
		$forward = $this->getResource($request, 'Forward');
		if ($forward) {
			// 设置forward为新的请求
			$request->setProperties('cmd', $forward);
		}
		
		return $forward;
	}
	
	/**
	 * getView、getForward
	 * @param \demo\controller\Request $request
	 * @param string $resType
	 */
	private function getResource(\demo\controller\Request $request, $resType) {
		$cmd = $request->getProperty('cmd');
		$previous = $request->getLastCommand();		
		$status = $previous->getStatus();
		$status = $status ? $status : 0;
		$acquire = "get{$resType}";
		
		// 按指定优先级获取view或forward 
		$resource = $this->controllerMap->$acquire($cmd, $status);
		if (!$resource) {
			$resource = $this->controllerMap->$acquire('default', $status);
		}
		if (!$resource) {
			$resource = $this->controllerMap->$acquire($cmd, 0);
		}
		if (!$resource) {
			$resource = $this->controllerMap->$acquire('default', 0);
		}
		
		return $resource;
	}
	
	public function getCommand(\demo\controller\Request $request) {
		$previous = $request->getLastCo