微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

MVC问题:是否应该在控制器或模型中放入表单验证规则?

如何解决MVC问题:是否应该在控制器或模型中放入表单验证规则?

| 一方面,表单验证可以看作是应用程序逻辑的一部分,因此属于模型。 另一方面,它直接处理来自视图的输入并处理显示错误等。从这个角度来看,将其放入控制器更有意义。 从MVC的角度来看,哪种方法是正确的? P.S我的表单验证实际上只包括编写字段列表,它们的规则,然后将其传递到表单验证库,该库会根据是否通过验证返回true / false。 例:
$this->load->library(\'form_validation\');
$this->form_validation->set_rules(\'name\',\'Name\',\'required\');
$this->form_validation->set_rules(\'email\',\'Email\',\'required|valid_email\');
//........
if ($this->form_validation->validate())
    // Process data
else
    $this->register_form(); //A controller action that will show a view with errors
应该将其放入控制器或模型中吗?     

解决方法

验证是模型的问题。只有模型知道您的数据的外观。您在模型中描述了数据字段,因此您应该在同一位置描述该字段的验证规则。 对我来说,这似乎很明显,但我很乐意听对手的话。     ,理想情况下,您需要3层验证: 查看:客户端(javascript,html5验证等)。这会在数据到达控制器之前捕获明显的错误和遗漏,从而浪费用户的时间并在出现错误时调用不必要的页面加载。 控制器:这是您的表单验证层。控制器通常旨在直接处理输入,并将其发送到模型。表单中的每个字段在数据库中都有一个直接相关的列是非常少见的,通常需要以某种方式更改数据,然后再将其传递给模型。仅仅因为您需要验证一个名为“确认电子邮件”的字段,并不意味着您的模型将处理一个“确认电子邮件”值。有时,这将是最后的验证步骤。 模型:这是您进行验证的最后一道防线,并且可能是在没有直接从表单发布而直接向模型发送数据的情况下进行的唯一验证。很多时候,您需要通过控制器调用或使用非用户输入的数据将数据发送到DB。我们不想看到数据库错误,我们希望看到应用程序本身抛出的错误。模型通常不应直接处理$ _POST数据或用户输入,而应从控制器接收数据。您不想在这里处理电子邮件确认之类的无用数据。     ,我想说,在大多数情况下,表单验证代码应该在控制器中(而不是模型中)。 Madmartigan在“表单验证!==数据验证。并非所有表单都与模型进行交互”上方的评论中对此表示最佳。 Web表单在逻辑上是MVC的“视图/控制器”部分的一部分,因为用户在视图中与其进行交互。     ,似乎每个人都总是说模型可以解决这个问题,它有其优点(与之相反),但是我认为问题的答案更加微妙。数据本身的验证应在模型上执行。 但是,还有其他类型的验证,例如,表单是否已使用意外字段提交(显然出于安全目的),或者用户是否有权进行请求的操作。通过将这些类型的验证放入模型中,它巩固了模型(数据的抽象)以完全分离事物,例如用户系统的工作方式或出于安全目的而评估表单提交的方式。 您可以想象更改这些类或类的系统之一,然后陷入混乱,因为您也必须更改所有模型。控制器是客户端输入和数据之间的中介者:以该角色,它们是上面示例以及其他许多示例的正确验证者。     ,考虑其他答案(和一些研究),如果您必须使用非空字段,电子邮件验证和填充之类的规则来验证数据,则Controller不应让该数据本身通过,但是如果您有诸如\ “只有声誉高于150的用户才能对答案投反对票”,您应该在模型层中执行此操作。 如果您想进行业务规则验证,我建议您拥有一个像“业务对象模式”之类的对象,在该软件的任何部分中,当您要“投票给答案”时,都应保留业务逻辑,集中。     ,这是一个有趣的理论讨论,但是如果我们关注的问题是在Codeigniter(CI)的上下文中提出的: 在CI中,您可以指定一个自定义验证规则,如下所示:
$this->form_validation->set_rules(\'email\',\'Email\',\'required|callback_my_validation\');
在这种情况下,您必须定义一个名为\“ my_validation \”的公用函数,该公用函数必须返回true或false,并且框架会将错误(如果返回false)添加到错误堆栈中。 所以...如果将这段代码放在控制器中,则会无意间公开一个公共URL,这意味着有可能调用\“ http://yoursite.com/my_validation \”之类的东西(我不认为您打算这样做)。 保护此URL的唯一方法是进入\“ routes.php \”文件,并阻止在那里访问该URL。这似乎不切实际,并且似乎向我们指出了CI开发人员希望我们处理模型验证的方向。     ,模型应验证其自己的数据。 假设您有一个“联系人”模型,只需要一个名字和电话号码。它应验证名字和电话号码是否已填写。 但是,如果此联系方式是报价的一部分,则可能还需要全名和电子邮件地址。 在这种情况下,您可以扩展Contact模型(成为QuoteContact模型)并添加更多验证,也可以对Quote模型进行额外的验证。 您应该编写模型以使其可在其他应用程序中重用(即使它们永远不会被使用),因此它们应独立于控制器。如果验证在控制器中,则如果您切换到命令行版本,则会丢失这些验证。     ,如果您使用codeigniter在服务器端验证表单,则它将在控制器中验证 您需要使用autoload这样包含form_validation库
$autoload[\'libraries\'] = array(\"form_validation\") 
或者直接在Controller中加载
$this->load->library(\'form_validation\');
然后将验证规则设置到每个表单字段
$this->form_validation->set_rules(\'username\',\'User Name\',\'required\');
$this->form_validation->set_rules(\'useremail\',\'User Email\',\'required|valid_email\');
如果在验证表单字段后发现任何错误,那么它将捕获validate函数
if ($this->form_validation->validate()) {
    //return back to form
} else {
    //successful validate all field 
}
    ,还有其他角度未涵盖在其他答案中。这取决于您在说控制器/视图是什么!如果是Javascript在用户输入时检查验证,则出于安全原因,您也应该在后端进行验证(这又可能在后端或模型的控制器中,因为任何人都可以在没有浏览器的情况下通过Ajax推送数据。 出于性能原因,您还应该在前端控制器/视图中进行验证,因为您不希望每次用户选择无效的出生日期或其他内容时都访问数据库。 因此,除了在M,V和/或C中进行验证的理论基础之外,还必须考虑前端与后端的实用性,而与MVC无关。 我个人的建议是不要将自己仅限于一个验证级别。错误的验证(如其他答案中提到的Confirm Password示例)可能会对体系结构产生严重影响。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。