在MVC中处理$ _POST数据的正确方法是什么?

时间:2012-11-13 11:16:26

标签: php model-view-controller post controller

我的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处理来自浏览器,网络服务,离线应用程序等的请求,或者每个人拥有它Controller?< / p>

5 个答案:

答案 0 :(得分: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()的方法 - 尽管我得出的结论是,在结构正确的应用程序中,GETPOST参数不应共享相同的名称。

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

它负责创建services (其中包含应用程序逻辑,同时将域业务逻辑保留在domain objects,这有助于您隔离交互领域实体和表示层的存储抽象之间。

关于其他选项:

  •   

    Controller仅调用Model,Model处理$ _POST数据。

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

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

  •   

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

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

结账单:

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

另一件事是:模型既不是类也不是对象。 Model is a layer


更新

  

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

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

为此,有两个条件:

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

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

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

答案 1 :(得分:3)

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

这一切都取决于你的MVC框架。通常,Controller执行用户和模型层之间的链接,模型层操纵域对象。

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

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

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

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

如今,模型层由将域对象与控制器的邪恶把握隔离开来的服务组成,以限制层之间的依赖关系到它们各自的接口。这是大多数请求处理完成的地方。

例如,

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

  • 请求首先变为对象
  • 使用路由对象路由该对象
  • 将其处理为控制器
  • 控制器通过构建响应对象的操作将请求传递给相关服务

然后分几个步骤打破服务工作:

  • 验证(使用依赖于单独文件中描述的规则的专用对象),
  • 构建/更新域对象(如果需要,使用序列化到/从db),
  • 选择回复模板,
  • 所述模板的填充以及来自域的相关数据。

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

请参阅this question以更好地了解一般概念。

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

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

答案 2 :(得分:1)

我正在使用Zend并关注

第二个选项。

注册表单示例

step-1 表单将post值发送给指定的控制器

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

步骤-3 将已检查的帖子数据以变量或整数发送给模型。

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

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

我认为无论您使用哪种框架或认可,您的第二种选择都会更好。

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

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

 it helps in keeping code readable managebale .

答案 3 :(得分:0)

查看一些MVC框架。

例如,在Yii中,您可以在操作

中编写此类代码
$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

答案 4 :(得分:0)

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

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

Yii绝对是MVC的干净实现。