深入PHP面向对象、模式与实践——企业模式(3)

xiaoxiao2021-02-28  79

表现层


前端控制器

前端控制器模式用一个中心来处理所有到来的请求,最后调用视图来将结果呈现给用户。

实现

前端控制器模式定义了一个中心入口,每个请求都要从这个入口进入系统。前端控制器处理请求并选择要执行的操作。

<?php namespace woo\controller; //... class Controller { private $applicationHelper; private function __construct() { } static function run() { $instance = new Controller(); $instance->init(); $instance->handleRequest(); } function init() { $applicationHelper = ApplicationHelper::instance(); $applicationHelper->init(); } function handleRequest() { $request = new \woo\controller\Request(); $cmd_r = new \woo\command\CommandResolver(); $cmd = $cmd_r->getCommand($request); $cmd->execute($request); } } class ApplicationHelper { private static $instance; private $config = "/tmp/data/woo_options.xml"; private function __construct() { } static function instance() { if (!self::$instance) { self::$instance = new self(); } return self::$instance; } function init() { $dsn = \woo\base\ApplicationRegistry::getDSN(); if (!is_null($dsn)) { return; } $this->getOptions(); } private function getOptions() { $this->ensure(file_exists($this->config), "Could not find options file"); $options = SimpleXml_load_file($this->config); print get_class($options); $dsn = (string)$options->dsn; $this->ensure($dsn, "No DSN found"); \woo\base\ApplicationRegistry::setDSN($dsn); // set other values } private function ensure($expr, $message) { if (!$expr) { throw new \woo\base\AppException($message); } } } class Request { private $properties; private $feedback = array(); function __construct() { $this->init(); \woo\base\RequestRegistry::setRequest($this); } function init() { if (isset($_SERVER['REQUEST_METHOD'])) { $this->properties = $_REQUEST; return; } foreach ($_SERVER['argv'] as $arg) { if (strpos($arg, '=')) { list($key, $val) = explode("=", $arg); $this->setProperty($key, $val); } } } function getProperty($key) { if (isset($this->properties[$key])) { return $this->properties[$key]; } } function setProperty($key, $val) { $this->properties[$key] = $val; } function addFeedback($msg) { array_push($this->feedback, $msg); } function getFeedback() { return $this->feedback; } function getFeedbackString($separator = "\n") { return implode($separator, $this->feedback); } } namespace woo\command; abstract class Command { final function __construct() { } function execute(\woo\controller\Request $request) { $this->doExecute($request); } abstract function doExecute(\woo\controller\Request $request); } class DefaultCommand extends Command { function doExecute(\woo\controller\Request $request) { $request->addFeedback("Welcome to WOO"); include("woo/view/main.php"); } } class CommandResolver { private static $base_cmd; private static $default_cmd; function __construct() { if (!self::$base_cmd) { self::$base_cmd = new \ReflectionClass("\woo\command\Command"); self::$default_cmd = new DefaultCommand(); } } function getCommand(\woo\controller\Request $request) { $cmd = $request->getProperty('cmd'); $sep = DIRECTORY_SEPARATOR; if (!$cmd) { return self::$default_cmd; } $cmd = str_replace(array('.', $sep), "", $cmd); $filepath = "woo{$sep}command{$sep}{$cmd}.php"; $classname = "woo\\command\\{$cmd}"; if (file_exists($filepath)) { @require_once("$filepath"); if (class_exists($classname)) { $cmd_class = new ReflectionClass($classname); if ($cmd_class->isSubClassOf(self::$base_cmd)) { return $cmd_class->newInstance(); } else { $request->addFeedback("command '$cmd' is not a Command"); } } } $request->addFeedback("command '$cmd' not found"); return clone self::$default_cmd; } } \woo\controller\Controller::run(); ?>

系统中的控制器复制分配任务给其他。其他类完成了绝大部分实际工作。

ApplicationHelper类并不是前端控制器的核心,但前端控制器通常都需要通过应用助手类来获取基本的配置数据。

前端控制器通常通过运行一个Command对象来调用应用程序逻辑。Command对象通常根据请求中的参数或URL的结构来决定选择哪一个命令。

如果你对项目需要很快完成,或者项目太小以至于前端控制器在系统中的比重太大,那么使用前端控制器就不太合适了。

转载请注明原文地址: https://www.6miu.com/read-57263.html

最新回复(0)