我是靠谱客的博主 雪白狗,最近开发中收集的这篇文章主要介绍php控制应用程序,[php]应用控制器(二),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

namespace democontroller;

/**

* 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 = democontrollerApplicationHelper::getInstance();

$appHelper->init();

}

private function handleReuqest() {

$request = new democontrollerRequest();

$appController = demobaseApplicationRegistry::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 democommandCommandReslover();

$cmd = $cmdReslover->getCommand($request);

$cmd->execute($request); */

}

private function invokeView($view) {

include("demo/view/{$view}.php");

exit();

}

}

handleRequest()里面的while循环是为了处理中有可能出现的,元素的值是对应的Command子类,这些、、和的关系都已经被映射到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 democontroller;

/**

* AppController

*/

class AppController {

private static $baseCmd;

private static $defaultCmd;

private $controllerMap;

// 标记已经执行过的Command,防止出现forward循环

private $invoked = array();

public function __construct(democontrollerControllerMap $camp) {

if (!isset(self::$baseCmd)) {

self::$baseCmd = new ReflectionClass('democommandCommand');

self::$defaultCmd = new democommandDefaultCommand();

}

$this->controllerMap = $camp;

}

public function getView(democontrollerRequest $request) {

$view = $this->getResource($request, 'View');

return $view;

}

public function getForward(democontrollerRequest $request) {

$forward = $this->getResource($request, 'Forward');

if ($forward) {

// 设置forward为新的请求

$request->setProperties('cmd', $forward);

}

return $forward;

}

/**

* getView、getForward

* @param democontrollerRequest $request

* @param string $resType

*/

private function getResource(democontrollerRequest $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(democontrollerRequest $request) {

$previous = $request->getLastCommand();

if (!$previous) {

// 当前为第一次请求

$cmd = $request->getProperty('cmd');

if (!$cmd) {

// cmd为空,返回default

$request->setProperties('cmd', 'default');

return self::$defaultCmd;

}

} else {

// 返回forward

$cmd = $this->getForward($request);

if (!$cmd) {

return null;

}

}

// 取得Command对象

$cmdObj = $this->resloveCommand($cmd);

if (!$cmdObj) {

throw new demobaseAppException("'Command {$cmd} not found!");

}

// 判断是否forward循环

$cmdClass = get_class($cmdObj);

if (isset($this->invoked[$cmdClass])) {

throw new demobaseAppException('Circular Forwarding!');

}

$this->invoked[$cmdClass] = true;

return $cmdObj;

}

/**

* 从ControllerMap中获取$cmd对应的映射

* @param string $cmd

*/

public function resloveCommand($cmd) {

$classroot = $this->controllerMap->getClassroot($cmd);

$sep = DIRECTORY_SEPARATOR;

$filePath = "demo{$sep}command{$sep}{$classroot}.php";

$className = "\demo\command\{$classroot}";

if (file_exists($filePath)) {

@require_once $filePath;

if (class_exists($className)) {

$cmdClass = new ReflectionClass($className);

if ($cmdClass->isSubclassOf(self::$baseCmd)) {

return $cmdClass->newInstance();

}

}

}

return null;

}

}

要注意的是Request对象,getResource和getCommand都是根据Request对象里面的cmd或者lastCommand来处理的。

应用控制器依然需要从请求的url中获取cmd来判断调用Command,但它能够利用来控制程序的流程,而且能够为一个可以产生许多不同反馈的页面安排不同的视图(比如表单,提交后可能是error、success等其它反馈视图)。

接下来就是视图模式了。模板视图是PHP自身拥有的功能,它可以和HTML标签结合在一起使用。这种方式的好处是能提高效率,但同时也会为后续开发和长期维护带来不良的后果。实现模板视图的方法是虚构一个模板系统,将特定的标签(tag)解析成系统中的值。当然也可以使用模板引擎,比如Smarty。

我们让视图只执行“显示数据”的功能,那么通常可以先获取数据,然后传递到视图。另一方面,视图助手(ViewHelper)能够帮助实现传递数据。我们可以为他针对一个视图设计,也可以为多个视图共享。

namespace demoview;

/**

* 视图助手

*/

class ViewHelper {

/**

* 返回request

*/

public function getRequest() {

return demobaseRequestRegistry::getInstance()->getRequest();

}

}

这里的ViewHelper很简单,以后可以只要有需求就可给它添加方法。

Controller和AppController都已经完成了,那么来看个具体的例子吧。

一个具体的Command子类,Login:

namespace democommand;

class Login extends Command {

protected function doExecute(democontrollerRequest $request) {

$userName = $request->getProperty('userName');

$password = $request->getProperty('password');

if (!$userName || !$password) {

// userName或者password的值不存在

$request->addFeedback('insuffiicient_data');

return self::status('CMD_INSUFFICIENT_DATA');

}

$user = new User($userName, $password);

// setObject

$request->setObject('loginUser', $user);

if ($userName == 'root' && $password == 'root') {

$request->addFeedback('login successfully!');

return self::status('CMD_OK');

} else {

return self::status('login falied!');

}

}

}

对于下面三个url请求,控制器都能得到预期的结果:

runner.php?cmd=Login&userName=root&password // CMD_INSUFFICIENT_DATA insufficient_data.php

runner.php?cmd=Login&userName=root&password=root // CMD_OK success.php

runner.php?cmd=Login&userName=root&password=123 // CMD_ERROR error.php

success.php:ViewHelper的例子:

require_once 'demo/view/ViewHelper.php';

$vh = new demoviewViewHelper();

$request = $vh->getRequest();

var_dump($request);

$obj = $request->getObject('loginUser');

?>

Login Success

Request Command <?php echo $request->getProperty('cmd'); ?>

Welcome <?php echo $obj->getName(); ?>

Your password <?php echo $obj->getPassword(); ?>

Testing...

下面为入口文件runner.php的代码:

use democontrollerController;

require_once 'demo/controller/Controller.php';

Controller::run();

现在已经能完成对请求的处理了,还控制了程序流程(上面就是一个例子)。一般的情况下很少用到应用控制器。如果只需要实现单一入口功能的话,一个入口文件(runner.php)直接解析url就能完成了。

控制器层和视图层已经完成了,业务逻辑层使用领域模型,因为它能够使用数据映射器中的大部分模式。

那么接下来需要实现持久化层了。

最后

以上就是雪白狗为你收集整理的php控制应用程序,[php]应用控制器(二)的全部内容,希望文章能够帮你解决php控制应用程序,[php]应用控制器(二)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部