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

表现层


前端控制器

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

实现

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

这里写图片描述

<?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的结构来决定选择哪一个命令。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值