3

我试图理解并找出在我的自定义框架中的控制器之间切换的好方法。以下示例是我目前正在考虑的,出于演示目的进行了简化,但如果有更好的方法,我真的很感激一些专家的建议?

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;
}
4

2 回答 2

3

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

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

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

    a)您肯定希望至少为所有控制器类创建一个接口来实现。调用它IController或类似的东西。这将在下一步中使用。

    b) 您必须满足于使用字符串作为类名来创建对象。$controllerObject = new $controller();“Route”处理程序类中的IE 。原因是要运行的控制器和操作名称直接来自请求 URL。这部分有别名的方法,但这完全是另一个问题。不要忘记验证和/或将这些从客户端传入的“控制器”类名列入白名单。验证:使用 PHP 函数class_exists($controller),然后 if true,检查以确保控制器类IController使用 PHP 的内置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您不希望客户端使用上述设计模式直接执行的方法(即以任何可能的值命名)。希望您的框架用户也能理解这一点。请务必正确记录其内部工作原理,以使您的框架用户了解。

当然还有比这更多的方法,但这取决于你——框架设计者。此外,操作应该对使用什么“视图”拥有最终决定权。如果操作没有明确说明要使用的视图,则可以设置默认值。但同样,那将是另一个问题。

于 2013-01-13T01:20:30.423 回答
0

你真的应该从阅读 MVC 到底是什么开始。我建议从 Fowler 的GUI Architectures开始。因为有一件事是非常确定的——你所拥有的不是它。

看起来,您所命名BaseController的实际上是在处理路由。这就是用户的请求 URL,并包含基于您从所述 URL 检索到的文件的文件。这既不是面向对象编程,也不是过程编程。你所拥有的就是所谓的非结构化编程

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

就像是:

$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

于 2013-01-14T15:44:00.010 回答