PHP MVC - 为什么要将控制器实例传递给视图类?

时间:2014-02-17 17:04:05

标签: php model-view-controller

我已经阅读了很多MVC文章,例如this sitethis。我仍然不明白为什么控制器应该传递给视图类?

<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);

if (isset($_GET['action']) && !empty($_GET['action'])) {
    $controller->{$_GET['action']}();
}

echo $view->output();

什么时候我们可以在bootstrap或前端控制器中调用控制器动作然后是什么目的呢?

$view = new View($controller, $model);

1 个答案:

答案 0 :(得分:2)

理论

在宏设计层面,MVC是一个架构决策,表明开发中有三个概念必须分开。模型,视图和控制器。

为避免在SO上出现更多的“MVC理论”重复,这是一个非常被接受的答案,其中解释了MVC的基础知识:https://stackoverflow.com/a/5864000/1311025

MVC的实现

您必须选择适合您的项目要求和变更视角的实施。

例如。如果我认为我的数据库将来会发生变化(我不知道什么时候,我只是怀疑它会改变)我会做一个绝对解耦我的数据库creating a layer that abstracts the implementation of it from the controller.的实现并实现一个提供的工厂您是访问数据库的正确实例。

如果我认为我的视图会发生变化,那么我将在视图中使用观察者模式来分离控制器和视图。通过事件,控制器和视图将进行通信。

然后,您可以按照满足您需求的软件设计模式构建自己的MVC实现。


现在,根据您提供的代码,

<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);

if (isset($_GET['action']) && !empty($_GET['action'])) {
    $controller->{$_GET['action']}();
}

echo $view->output();

思想是分离类(模型,视图和控制器)中的职责,对我来说,这是一个将视图与模型耦合的示例。但是,如果我们希望视图,控制器和模型将永远像这样并且永远不会改变,那就是正确的 此外,通过这种实现,控制器具有一个状态,反映出这种状态永远不会扩展(或者不是很容易)。

  

免责声明:这是我对简单,快速和小项目的实施。   如果您需要更严格的解决方案,那么质量不是一种选择,   那么你必须遵循更严格的指导方针。

在我看来,我会选择至少将视图与模型分离。

<?php
$controller = new Controller();
if (isset($_GET['action']) && !empty($_GET['action'])) {
    $controller->doAction($_GET['action']);
}

控制器不必处理全局php变量($ _GET):

<?php
Controller {
     public function __construct() {}

     public function doAction($action) {
        $model = new User();
        $model->setName("user36279");

        //This just transforms the user model in an associative array
        $UserDTO = $model->toDTO();
        $view = new UserView();
        //We don't send the model to the view increasing decoupling  
        $view->render($UserDTO);
     } 
}

但这将是我的实施。现在您可以选择决定要分离多少,可维护性,复杂性和可测试性。

修改
有人指出:

  

[...]您的“控制器”实际上负责路由,检索   来自模型层的信息和响应的呈现,以及   当然违反了SRP和SoC。底线:所有这些都是   完全错了

他是对的,我的代码违反了SRP。但看看这个问题:
Does the traditional use of the controller in MVC lead to a violation of the Single Responsibility Principle?

  

如果您想关注SRP,则需要对Controller进行分解   进入Dispatcher和Actions; Dispatcher将控制权分派给   它的行动[...]

     

为什么我们不经常看到这个?因为控制器通常是“广告   特殊的“实现,叶级别的具体类,不是   概括的,并不意味着是子类。这里使用了这个类   更方便的是对代码进行分组,几乎可以肯定   非公开的(可能是私人的,也许是受保护的),“仅仅是”内部的   实施细节。

     

选择如何决定要发送的动作,数量和   可能的行动的多样性,高度,调度和行动   紧密耦合。 所以在实践中,通常更容易   代码集中在一个地方。

SOLID原则是设计面向对象的重要指南。这里的一般规则是承认不同的选择,并选择最适合您需求的选择。原则是指导而非规则,遵循这些原则的主要优点是一组与语言无关的通用解决方案,易于使用和理解新手和专家开发人员以及我们设计的简单性。

结论:当您需要应用SRP(单一责任原则)并因此实施SOLID时,由您决定。