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

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

a) Controller只调用ModelModel处理$_POST数据。
b) Controller$_POST数据转换成variables并传递给Model
c) Controller$_POST数据转换成一个Model的域对象,并只传递给Model

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

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

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

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

最好的select是使用#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实例的方法来抽象用户的input,则不需要实际创buildvariables。

另外,你可能想用Request::getPost()这样的东西replaceRequest::getParam()方法 – 尽pipe我得出结论:在一个正确结构化的应用程序中, GETPOST参数不应该共享相同的名字。

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

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

关于其他选项:

  • Controller只调用Model和Model处理$ _POST数据。

    在MVC和MVC灵感的devise模式中,模型应该既不认识用户界面,也不认识整个表示层。 PHP中的$_POSTvariables是超全局的 。

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

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

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

闭幕笔记:

有一件事你必须明白的是,在基于Web的MVC应用程序中,应用程序的用户就是浏览器。 不是你。 浏览器发送请求,由路由机制处理并由控制器分发。 并且视图产生对你的浏览器的响应。

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


更新

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

你应该可以有单一的控制器,处理所有的应用forms。 但这只是条件,你实际上使用同一个应用程序的所有3个用例。

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

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

这样你可以有一个应用程序来满足所有的要求。 唯一的事情就是每个变体都有不同的引导阶段,在这个阶段你创buildRequest实例并select正确的视图。

在你所描述的情况下,变化的部分实际上就是视图,因为REST或SOAP服务将会产生与普通Web应用程序不同的响应。

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

这一切都取决于你的MVC框架。 通常情况下,控制器会在用户和模型层之间build立链接,从而操纵域对象。

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

其他人用专用方法(胖模型)embedded对象模型中的大部分处理。

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

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

现在,模型层是由将域对象从控制器的邪恶的把握中分离出来的服务组成的,以限制层与各自接口之间的依赖关系。 这是大多数请求处理完成的地方。

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

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

服务工作然后分几步进行:

  • validation(使用依赖于单独文件中描述的规则的专用对象),
  • 构build/更新域对象(如果需要,使用从/到数据库的序列化),
  • select响应的模板,
  • 所述模板的种群与来自域的相关数据。

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

看到这个问题 ,以更好地了解一般概念。

看到这个其他问题的其他答案。

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

我正在使用Zend和以下

第二个选项。

示例aregistry单

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

步骤-2我会通过服务器端validation来validation表单值(例如邮件和url以及空邮政值)。

步骤-3将检查的岗位数据发送到variables或者整个模型中。

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

步骤 -5模型插入post值并创build一个新用户。

我认为你的第二个select是更好的,无论你使用的框架或approah。

注 – 相同的控制器可以处理everthing取决于您的应用程序逻辑。

  but i prefer to keep different controller for differnt user request and user types it helps in keeping code readable managebale . 

看看一些MVC框架。

例如,在Yii中,你可以在动作中写下这样的代码:

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

请注意,您的模型的所有attributes都必须通过validation规则。 在Yiivalidation期间(实际上,之前) $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

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

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

Yii绝对是一个干净的MVC实现。