37

我的 PHP 系统中有常见的 MVC 情况:接收来自包含数据Controller的请求。现在我有三种方法来处理数据:View$_POST

a)Controller唯一调用ModelModel处理$_POST数据。
b) 将Controller数据$_POST转换为变量并将它们传递给Model.
c)Controller$_POST数据转换为Model的域对象,并且仅将对象传递给Model

目前,我正在关注选项A,但我认为这是错误的,所以我正在考虑使用选项C。

那么,根据 MVC,处理$_POST数据的正确方法是什么?

编辑目前,我没有使用任何 MVC 框架。

编辑 2通常,相同的Controller处理来自浏览器、Web 服务、离线应用程序等的请求,或者每个都有它自己的请求Controller

4

5 回答 5

26

最好的选择是使用#2方法,并进行一些更改。
我会把它写成这样:

public function postLogin( $request )
{
     $service = $this->serviceFactory->build('Recognition');
     $service->authenticate( $request->getParam('username'),
                             $request->getParam('password') );
}
// Yes, that's the whole method

Request如果您使用了诸如实例之类的东西来抽象用户的输入,则无需实际创建变量。

此外,您可能希望Request::getParam()用类似的方法替换该方法Request::getPost()- 尽管我得出的结论是,在结构正确的应用程序中,GETandPOST参数不应共享相同的名称。

您在代码片段中看到的serviceFactory将是您在控制器和视图实例中注入的对象。它可以让您在控制器和视图之间共享相同的服务实例。

它负责创建服务 (将包含应用程序逻辑,同时将域业务逻辑留在域对象中),这有助于您将域实体和存储抽象之间的交互与表示层隔离开来。

关于其他选项:

  • 控制器只调用模型,模型处理 $_POST 数据。

    在 MVC 和受 MVC 启发的设计模式中,模型应该既不了解用户界面,也不了解整个表示层。PHP 中的$_POST变量是一个超全局的.

    如果您将它与模型层一起使用,您的代码将绑定到 Web 界面甚至特定的请求方法。

  • Controller 将 $_POST 数据转换为 Model 的对象,并且只将对象传递给 Model

    不完全确定你的意思。似乎您在谈论抽象的实例化,它将包含用户的请求。但在这种情况下,控制器将负责所述结构的实例化/创建,这将违反SRP

结束语:

您必须了解的一件事是,在基于 Web 的 MVC 应用程序的上下文中,您的应用程序的用户是浏览器。不是你。浏览器发送请求,请求由路由机制处理,由控制器传播。并且视图产生对您的浏览器的响应。

另一件事是:模型既不是类也不是对象。模型是一层


更新

通常,同一个 Controller 处理来自浏览器、Web 服务、离线应用程序等的请求,还是每个都有自己的 Controller?

您应该能够拥有处理所有形式的应用程序的单个控制器。但这只是在条件下,您实际上对所有 3 个用例都使用相同的应用程序。

要做到这一点,有两个条件:

  • 您需要抽象该Request控制器接收的实例
  • 视图应该在控制器外部实例化

这样您就可以拥有一个应用程序来满足所有要求。唯一不同的是,每个变体都有不同的是引导阶段,您可以在其中创建Request实例并选择正确的视图。

在您所描述的情况下,更改部分实际上是视图,因为 REST 或 SOAP 服务预计会产生与普通 Web 应用程序不同的响应。

于 2012-11-15T11:44:22.057 回答
3

曾几何时是三层应用程序架构。

这一切都取决于您的 MVC 框架。通常,控制器负责用户和模型层之间的链接,模型层操作域对象。

在 PHP 的 MVC 早期,模型层实际上只是领域对象,为此目的称为模型。有些人更喜欢所谓的瘦模型,它只提供数据的面向对象表示(这简化了持久性)。在这种情况下,控制器将重新组合所谓的操作,其中包含与 HTTP 请求相关的大部分处理(胖控制器)。

其他人使用专用方法(胖模型)将大部分所述处理嵌入到对象模型中。

但是,在某些时候,您必须分析查询的内容以对其进行清理和验证,这取决于您的视图将如何格式化请求。清理可能是一个控制器任务(这个请求应该只包含这些值),而验证肯定是一个模型任务(值应该是这些类型)。

一个有趣的问题是:您如何处理影响多个域对象的操作?你把它的逻辑放在哪里?

如今,模型层由将域对象与控制器的邪恶控制分离的服务组成,以将层之间的依赖关系限制在各自的接口上。这是完成大部分请求处理的地方。

例如, Symfony2为这个问题提供了一个明智的答案:处理请求的每个步骤都在一段专用代码中实现,可以描述如下:

  • 请求首先变成一个对象
  • 该对象是使用路由对象路由的
  • 它被处理给控制器
  • 控制器将请求传递给操作所涉及的服务,该操作构建响应对象

然后,服务作业分几个步骤中断:

  • 验证(使用依赖于单独文件中描述的规则的专用对象),
  • 域对象的构造/更新(必要时使用到/从数据库的序列化),
  • 选择响应模板,
  • 使用来自域的相关数据填充所述模板。

CakePHP是另一个流行的框架,它遵循类似的概念:简单的控制器和封装域对象的服务。

请参阅此问题以更好地了解一般概念。

有关其他答案,请参阅this other question

感谢tereško对此事的宝贵意见。

于 2012-11-13T11:54:47.757 回答
1

我正在使用 Zend 并关注

第二个选项。

示例注册表

步骤 1 表单将后值发送给指定的控制器

步骤 -2我将通过服务器端验证验证表单值(例如邮件和 url 以及空帖子值)。

步骤 -3将检查过的发布数据以变量或完整的形式发送到模型。

第 4 步- 控制器调用模型。

步骤-5 模型插入帖子值并创建一个新用户。

我认为无论您使用何种框架或方法,您的第二个选项都会更好。

注意 - 相同的控制器可以处理一切取决于您的应用程序逻辑。

 but i prefer to keep different controller for differnt user request and user types

 it helps in keeping code readable managebale .
于 2012-11-22T13:54:38.070 回答
0

查看一些 MVC 框架。

例如,在 Yii 中,您可以在action中编写这样的代码:

$model = new Model();
if(isset($_POST['Model'])) {
    $model->attributes = $_POST['Model'];
}

请注意,attributes您的所有模型都必须通过验证规则。在 Yii 中验证适用于(实际上是之前)$model->save()

看:

  1. http://www.yiiframework.com/doc/guide/1.1/en/form.model#securing-attribute-assignments
  2. http://www.yiiframework.com/doc/guide/1.1/en/basics.mvc
于 2012-11-13T11:26:33.877 回答
0

'C' 是最好的选择。您不应该让原始 $POST 数据进入模型,因为模型应该主要是通用处理存储和加载操作。

示例:可以使用相同的模型来使用 Web 界面和 Web 服务。在 Web 上 $_POST 有效,但对于 Web 服务则无效。所以模型不关心如何接收数据,只关心如何存储和加载它。

Yii 绝对是 MVC 的干净实现。

于 2012-11-15T13:48:34.167 回答