2013-01-12 58 views
3

我想了解并找出在自定义框架中的控制器之间切换的好方法。以下示例是我目前的想法,为了演示目的而进行了简化,但如果有更好的方法,我会非常感谢一些专家的建议。在控制器之间切换(MVC)

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; 
} 
+1

您是否打算允许您的框架用户使用自定义操作实现自定义控制器? –

+0

@ bob-the-destroyer如果这样可以使代码更加通用,并且我假设它会,那么是的。 –

回答

3

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

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

  2. 如果你希望你的框架,用户可以用自定义操作创建自定义控制器:

    a)你肯定会想创造至少为所有控制器类来实现的接口。叫它IController或类似的东西。这用于下一步。

    b)您将不得不使用字符串作为类名创建对象。 IE“$controllerObject = new $controller();”在“Route”处理程序类中。原因在于要运行的控制器和操作名称直接来自请求URL。这部分有混淆的方法,但这完全是另一个问题。做而不是忘记验证和/或白名单从客户端传入的这些“控制器”类名称。验证:使用PHP函数class_exists($controller),然后如果是true,请检查以确保控制器类使用PHP的内置class_implements($controller)实现IController。只有然后您应该执行$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(); 
    } 
    

    三)没有你的控制器声明任何方法(即命名与任何$action可能的价值)你不希望客户直接使用这种上述设计模式执行。希望你的框架用户也能理解这一点。只要确保正确记录了它的内部工作方式,以使您的框架用户了解。

当然,还有比这更多的方法,但这取决于你 - 框架设计师。此外,该行动应该在使用“观点”时拥有最终决定权。如果操作没有明确说明要使用的视图,可以设置默认值。但是,这又是一个问题。

+0

+1用于重命名该类。假设控制器有一个父级基类,这对名称来说是一个更好的选择。 – Chief

0

你真的应该首先看看MVC究竟是什么。我建议先从福勒的GUI Architectures开始。因为有一件事是非常确定的 - 你拥有的不是它。

看起来,你所命名的BaseController实际上是处理路由。它表示用户的请求URL,并包含基于您从所述URL检索到的文件的文件。这既不是面向对象编程,也不是程序编程。你在那里有什么被称为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模式旨在为大型项目带来一些订单。如果你使用它来创建一个简单的博客/名片网站,这看起来像是一个矫枉过正(假设页面不增长)。

P.S.您可能会发现以下对您的学习有用的链接:this,this,thisthis