一方面,表单验证可以被视为应用程序逻辑的一部分,因此属于模型。
另一方面,它直接处理来自视图的输入并处理显示错误等。从这个角度来看,将它放入控制器更有意义。
从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
是否应该将其放入控制器或模型中?
答案 0 :(得分:72)
理想情况下,您需要3层验证:
答案 1 :(得分:19)
验证是Model的问题。只有模型知道您的数据应该是什么样子。您在模型中描述了数据字段,因此您应该在同一位置描述此字段的验证规则。
这对我来说似乎很明显,但我很乐意听取对手的意见。
答案 2 :(得分:12)
我想说在大多数情况下,表单验证代码应该在控制器(而不是模型)中。
Madmartigan在上面的评论中说得最好“表单验证!==数据验证。并非所有表单都与模型互动”
Web表单在逻辑上是MVC的View / Controller部分的一部分,因为用户在视图中与它们交互。
答案 3 :(得分:5)
似乎每个人总是说模型提到这个问题,这有其优点(与相反的情况相比),但我认为这个问题的答案更加微妙。 应在模型上执行数据本身的验证。
但还有其他类型的验证,例如表单是否已提交了意外字段(显然是出于安全目的),或者用户是否有权请求操作。通过在模型中放置这些类型的验证,它可以粘合模型(数据的抽象)以完全分离事物,例如用户系统如何工作或如何为安全目的评估表单提交。
您可以想象更改其中一个类或类系统,然后弄乱,因为您还必须更改所有模型。而控制器是客户端输入和数据之间的中介:在该角色中,它们是上述示例的适当验证器,可能还有许多其他验证器。
答案 4 :(得分:2)
考虑到其他答案(以及一些研究),如果您必须使用非空字段,电子邮件验证和内容等规则验证数据,则Controller不应让这些数据通过自身,但如果您有规则例如“只有信誉大于150的用户可以拒绝回答”,你应该在模型层中这样做。
如果您想要进行业务规则验证,我建议您在软件的任何部分使用Business Object Pattern这样的对象,当您想要“拒绝回答”时,您就拥有了自己的业务逻辑保留和集中。
答案 5 :(得分:2)
这是一个有趣的理论讨论,但如果我们关注的问题是在Codeigniter(CI)的背景下做出的:
在CI中,您可以指定自定义验证规则,如下所示:
$this->form_validation->set_rules('email', 'Email', 'required|callback_my_validation');
在这种情况下,您必须定义一个名为“my_validation”的公共函数,该函数必须返回true或false,并且框架会将错误(如果返回false)添加到一堆错误。
所以...如果你把这个代码放在控制器中,你就是无意中暴露公共网址,这意味着它可能会调用类似“http://yoursite.com/my_validation”的东西(我不喜欢不认为你打算这样做。 保护此URL的唯一方法是进入“routes.php”文件并阻止访问此URL。这似乎并不实用,似乎指出CI开发人员希望我们在模型中处理验证的方向。
答案 6 :(得分:1)
该模型应验证自己的数据。
假设您有联系模式,只需要名字和电话号码。它应该验证填写的名字和电话号码。
但是,如果此联系人型号是报价的一部分,您可能还需要一个全名和电子邮件地址。
在这种情况下,您可以扩展Contact模型(成为QuoteContact模型)并添加更多验证,或者您可以在Quote模型上进行额外验证。
您应该编写模型以便在其他应用程序中重复使用(即使它们永远不会),因此它们应独立于控制器。如果验证在控制器中,那么如果切换到说命令行版本,则会丢失这些验证。
答案 7 :(得分:0)
如果使用codeigniter在服务器端验证表单,则在控制器中验证
您需要使用像此一样的自动加载包含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');
如果在验证表单字段后发现任何错误,则会捕获验证函数
if ($this->form_validation->validate()) {
//return back to form
} else {
//successful validate all field
}
答案 8 :(得分:0)
其他答案中没有涉及到另一个角度。这取决于你在说什么控制器/视图!如果Javascript在用户输入时检查验证,则出于安全原因,您的后端也应该进行验证(这可能会再次出现在后端的控制器中)或模型,因为任何人都可以在没有浏览器的情况下通过Ajax推送数据。
对于性能原因,您应该在前端控制器/视图中进行验证,因为每次用户选择无效的出生日期或某事时您都不想访问数据库
除了M,V,和/或 C中验证的理论基础之外,您还必须考虑前端与后端的实用性,而不考虑MVC。
我个人的建议是不要仅限于一级验证。错误的验证(如其他答案中提到的确认密码示例)会对架构产生严重影响。