MVC中控制器的工作是什么?

时间:2010-01-17 09:25:19

标签: model-view-controller

我正在尝试学习MVC架构。但我无法理解为什么你需要一个控制器。请参阅以下代码了解我的模型和视图。

model.php连接到数据库并检索帖子。 view.php将只显示帖子。

model.php

<?php
  $db = mysql_connect("somehostname", "someuser", constant("somepassword"));
  mysql_select_db("somedatabase", $db);

  $result = mysql_query("SELECT post FROM posts WHERE postid='" . $_POST['id'] . "'");
  $row = mysql_fetch_array($result);

  $post = $row["post"];

  mysql_close($db);
?>

view.php

<?php
  require "model.php";
  echo $post;
?>

我将浏览器位置设置为http://whateverhost/view.php?id=5

这会加载id为5的帖子。我这里不需要控制器。所以我很困惑为什么你需要一个控制器?

注意:请参考上面的例子说明。我不是编程爱好者,像CakePHP等学习东西对我来说是压倒性的。

编辑:如果你可以将controller.php添加到上面的代码中会很棒。这将有助于我理解控制器的作用以及它如何与模型和视图进行通信。

6 个答案:

答案 0 :(得分:14)

您不需要控制器,因为您的示例很简单。 一个真实案例场景的例子:

假设您有一个CAD应用程序。 CAD应用程序被安排为MVC。你有:

  • 一个视图,负责绘制当前模型,并提供可点击的实体。
  • 一个模型,用于保持当前数据的表示
  • 一个控制器,其作用是从视图中获取事件,并将它们转换为适当的实体,以便修改模型。

例如,用户点击一个正方形并删除它。控制器将从视图接收事件,创建表示命令的对象(通过命令模式),将其添加到队列中以执行撤消功能并执行命令。然后该命令将修改模型,但是将视图事件转换为修改模型的复杂机制的责任由控制器负责。

当然你可以说,为什么不创建Command对象的视图呢?好吧,没有人禁止你这样做,但你最终会将表达逻辑与操作逻辑混合在一起。这违背了良好的设计,尽管对于最琐碎的情况,你可以忍受这种设计。例如,如果您的CAD应用程序允许您将对象列表显示为3D表示和实体列表,并且您可以从两者中删除,则可以清楚地看到两个视图都实现了相同的逻辑来处理命令模式(糟糕的设计),或者他们只是将相同的消息传递给一个公共控制器(好的设计,MVC)。

答案 1 :(得分:9)

IMO ...

MVC是一种非常通用的设计模式,并不一定表示什么是好的,什么是坏的。有一个模型,一个视图和一个控制器。每个事物的责任取决于MVC的风格,您选择的MVC的风格应取决于项目的复杂程度。例如,如果您有一个域驱动项目,那么其他人给出的示例将无法正常运行。

所以它的基础是:

模型:具有将在视图中显示的数据的对象。这里是否真的没有定义DTO或域模型,但我会在一秒钟内分享我的想法。

查看:用户看到的内容以及用户的交互方式。这里的任何代码或逻辑都应该直接支持视图。换句话说,ZERO业务逻辑,ZERO数据访问逻辑,ZERO知识超出用户实际看到的任何东西。 Web表单,桌面窗口表单或活动(移动)等...

控制器:可能是这个难题中最模糊的部分。有一件事是肯定的,它在视图和&#34;模型之间进行调解。并且还决定接下来会发生什么,或者更确切地说,它控制&#39;流动。但重要的是不要把这种描述放得太远。这件事真正取决于你对MVC的理解。所以我将分享我在网络环境中看待它的方式;但基本上,只需在控制服务流和实际执行服务之间划一条线。

对我来说,MVC并不是一种描述N层的不同方式,正如一些人可能会声称的那样。 MVC中没有层,因为 MVC实际上是在您的表示层。 MVC的每个元素实际上都存在于表示层中,而MVC模式只是说你应该分开获取数据和显示数据之间的关注点:

  • 型号:数据是什么样的。实际上只是视图将用于获取其数据的结构
  • 查看:实际显示
  • 控制器:确定从何处获取模型的数据,甚至模型本身。

如果你能接受这个陈述,那么它应该有助于澄清模型在这种情况下的真正含义。该模型不是数据访问对象,并且该模型不是域模型,因为这些事物都不应该在您的表示层中。这样我们就可以使用ViewModel(MVVM)或DTO。为了简单起见,我将使用DTO。

因此,如果我们接受DTO作为我们在谈论&#34;模型&#34;时所讨论的模型类型。在MVC中,那我们从哪里得到它?如果控制器不应该搞乱数据访问,那么在哪里?你的服务层怎么样?您的服务层包含所有&#34;如何&#34;你的申请。这是&#34;做东西&#34;层。因此,如果您的视图想要创建用户,它将收集数据并将其交给控制器。控制器决定调用哪些服务以完成任务,并向其发送带有必要数据的请求。服务层以DTO响应。该DTO既可以直接使用,也可以添加到另一个模型中(例如,如果有多个服务被调用)。

重点是:

  • 控制器对您的域名一无所知(如果您有域名),它只知道您的可用服务以及如何调用它们。
  • 控制器绝对不会执行业务逻辑。例如,如果您需要在CreateUser操作中发送欢迎电子邮件,则控制器不会启动该电子邮件,因为这在技术上是业务规则。它将在您的服务和域图层之间处理。
  • 在我看来,您的控制器也不应该执行任何数据访问。这应该委托给服务层。许多教程倾向于显示控制器与存储库交互,我认为这很好,因为它是一个抽象,但直接数据访问在表示层中应该绝对没有。

再次,这在网络环境中。如果你在Android应用程序中使用MVC,也许你没有服务层或域。也许你会与不同种类的物体互动。就个人而言,我总是使用服务或应用层,并且出于几个原因,可能会或可能不会被视为对他人有价值。

所以在MVC.Net中,控制器更像是一个API;视图和API是两种不同的表示介质,它们可以协同工作(后端控制器提供数据,前端控制器使用该数据构建模型并与视图协调)。在Angular中,控制器更像我们在这里谈论的内容。看起来层层的图层。概念化有点令人困惑,但这个概念实际上并没有超出表示层。

但总结一下:控制器&#34;控制&#34;进出系统的操作和数据,进出视图,但实际上并不是业务。该过程的细节在很大程度上取决于您对项目的设计理念。

MVC with N-Tier

因此,在此图中,我将概念分组,以在典型的单片应用程序中显示N层内的MVC。通信从左向右运行,不会跳过任何其他层(请参阅:洋葱架构)。在表示层中,控制器知道模型和视图,但视图和模型大部分都不知道。但是,在许多类型的MVC中,包括ASP.Net和MVVM,视图可能知道模型的接口或原型(但不是模型实例),因此它可以绑定到它

控制器将处理模型(或此上下文中的视图模型)的操作,这意味着它可能需要了解域对象和域服务。如果您想要一个更可重用的应用程序(例如,您的应用程序可以有多个头:Web API和桌面应用程序以及移动应用程序等),您可以选择在表示层和域之间插入一个应用程序层来提供交易边界和进一步隔离。重要的是视图对此体系结构中的域对象没有知识/依赖性 - 这就是为什么视图的单独模型的原因。 MVC中模型的要点是为视图创建模型。也就是说,它是专门为视图而不是域提供服务的模型。视图模型可以包装/调整域模型,只要它不会公开和/或意外地序列化。

另一方面,&#34;表示层&#34;在我看来,在Web API中,是序列化合同(例如JSON或XML)。所以相应地对待它。

答案 2 :(得分:2)

我认为在这种情况下可能会使用控制器,并显示代码。

<强> MODEL:

<?php
  $db = mysql_connect("somehostname", "someuser", constant("somepassword"));
  mysql_select_db("somedatabase", $db);

  $result = mysql_query("SELECT post FROM posts WHERE postid='" . $_POST['id'] . "'");
  $row = mysql_fetch_array($result);

  $post = $row["post"];

  mysql_close($db);

function getPost() {
    return $post;
}
?>

查看:

<html>
<head></head>
<body>
    <input type="submit" onClick="postToScreen();" value="Post">
    <p id="post"></p>
</body>
</html>

<强>控制器:

<?php
    $controllerPost = getPost();
?>

<script type="text/javascript">
function postToScreen() {
    document.getElementById("post").innerHTML="<?php echo $controllerPost; ?>";
}
</script>

我的javascript生锈了。我认为我的代码是正确的,但在将它放入任何东西之前,请仔细检查它。控制器控制视图的外观,在某些情况下,控制模型包含的数据。

答案 3 :(得分:1)

model.php 在这种情况下你是控制器。

如果你没有一个好的MVC框架(普通的PHP不是一个好的),模型,视图和控制器的角色就不容易区分。

模型是您在数据库中持久化的数据结构。在代码方面,如果主要由数据结构组成一个类。

视图只显示数据。主要是带有一些脚本标签的html。

控制器控制发生的事情。例如,用户编辑帖子。数据由控制器接收,可能稍微修改一下(添加时间戳,用户ip)并发送到模型以便存储它。然后控制器决定下一个要显示的视图以及要为新视图提取的数据。

只是一个小例子。

答案 4 :(得分:0)

IMHO 在MVC中,控制器有两个主要目的

  1. GUI逻辑的可测试性或GUI触发的任何内容。在大多数情况下,您可以相对容易地为控制器编写单元测试,例如,对于PHP或Windows Forms这样的GUI来说要困难得多。前者依赖于浏览器,后者依赖于Windows消息,在编写单元测试时,两者都不会让您的生活更轻松。它与任何其他表示层技术几乎相同。
  2. 表示层的可互换性或(在某些情况下)控制器。在某些情况下,您可以在两个GUI中使用相同的控制器(特殊情况下为“轻型”形式,另一种情况下为“丰富”形式),反之亦然(不常见)。
  3. 在功能比示例更多的场景中,您将看到优势。但是您应该决定支持还是反对MVC,并在每种形式的应用程序中使用相同的方法,不要混用它。我更喜欢MVC,你几乎总是需要控制器逻辑。

答案 5 :(得分:0)

我会尽量回答标题中的问题。那么,控制器在MVC中的作用是什么?

它的工作是成为一种模型格式来查看格式转换器,以便不具备UI驱动模型和UI驱动的数据库结构。

我们的想法是开发业务逻辑驱动的数据库结构,然后开发一个独立的UI。现在,当我们添加或移动一些UI控件时,我们的模型和数据库结构不应该改变。