在控制器之间切换(MVC)

时间:2013-01-12 23:23:01

标签: php oop model-view-controller

我正在尝试理解并找出在自定义框架中切换控制器的好方法。以下示例是我目前正在考虑的,为了演示目的而简化,但如果有更好的方法,我会非常感谢一些专家建议吗?

class BaseController() {
    function __construct() {
        $this->model = new ModelFactory();
        $this->view = new View();

        if(isset($_SERVER['QUERY_STRING'])) {
            list($controller, $action) = explode('=', $_SERVER['QUERY_STRING']);
            self::process($controller);
        }
    }

    public function process($controller) {
        switch($controller) {
            case 'user':
                $user = new UserController($action);
            break;

            case 'forum':
                $forum = new ForumController($action);
            break;

            default:
                // use base controller
                switch($action) {
                    case 'contact':
                        $this->view->load($action);
                    break;
                }
        }
    }
}

// inside UserController.php
switch($action) {
    case 'register':
    break;

    case 'login':
    break;
}

// inside ForumController.php
switch($action) {
    case 'new_thread':
    break;

    case 'edit_post':
    break;
}

2 个答案:

答案 0 :(得分:3)

这实际上是一个部分答案,希望能给你一些好的指示。我相信有更好答案的人会来。

  1. 您示例中的BaseController可能名称错误。你拥有它使它看起来更像一个控制器工厂,而不是所有其他控制器类可能派生的基本控制器。看起来这更像是一个“路由”类,所以你应该考虑给它一个更合适的名字。

  2. 如果您希望框架用户使用自定义操作创建自定义控制器:

    a)你肯定想要为所有控制器类创建至少一个接口来实现。称之为IController或类似的东西。这将在下一步中使用。

    b)你必须满足于使用字符串作为类名创建对象。 “Route”处理程序类中的IE $controllerObject = new $controller();。原因是要运行的控制器和操作名称直接来自请求URL。这部分有别名的方法,但这完全是另一个问题。 忘记验证和/或列入从客户端传入的这些“控制器”类名称。要验证:使用PHP函数class_exists($controller)然后如果true,请检查以确保控制器类使用PHP的内置IController实现class_implements($controller)。只有然后才能$controllerObject = new $controller();实际创建控制器对象。

    您的“路由”process方法会变得更像(并且请记住这是非常简化示例):

    public function process($controller, $action) {
        if (!class_exists($controller)) {
            throw new Exception('Controller class does not exist.');
        }
        if (!in_array("IController", class_implements($controller))) {
            throw new Exception('Route is not a valid controller.');
        }
        if (!method_exists($controller, $action)) {
            throw new Exception('No such action for requested controller.');
        }
        $ctrl = new $controller();
        return $ctrl->$action();
    }
    

    c)不要让你的控制器声明任何方法(即使用$action可能的值命名)你不希望客户端使用上面的设计模式直接执行。希望您的框架用户也能理解这一点。请务必在内部正确记录其工作原理,以便让您的框架用户了解。

  3. 当然还有更多的方法,但这取决于你 - 框架设计师。此外,该动作应该在使用什么“视图”中具有最终发言权。如果操作没有明确说明要使用的视图,则可以设置默认值。但同样,这将是另一个问题。

答案 1 :(得分:0)

你真的应该首先阅读MVC实际上是什么。我建议从福勒的GUI Architectures开始。因为有一件事是非常肯定的 - 你所拥有的不是它。

看起来,你所谓的BaseController,实际上是在处理路由。它是用户的请求URL,并包含基于您从所述URL检索到的内容的文件。这既不是OOP也不是程序编程。你在那里所拥有的是non-structured programming

而不是这种疯狂,你应该创建一个单独的类,为你的应用程序实现路由机制。根据您使用所述结构提取的数据,您应该启动特定的控制器实例,并在其上调用方法。

类似的东西:

$request = new Request('QUERY_STRING');

$router = new Router;
$router->import('/path/to/routing/config.file');
$router->route( $request );

$klass = $request->getParameter('controller');

if (class_exists( $controller ))
{
    $command = $request->getMethod() . $request->getParameter('action');
} 
else 
{
    $klass = 'Error';
    $command = 'getMessage';
}

$controller = new $klass;
$controller->{$command}( $request );

这当然是一个非常简化的版本。 MVC模式旨在为大型项目带来一些订单。如果你用它来创建像一个简单的博客/商务卡网站,它似乎是一种矫枉过正(假设页面没有增长)。

  

PS 您可能会发现以下链接对您的学习有用:thisthisthisthis。< /子>