我知道像这样的问题在stackoverflow上已经被问过很多次了,但即使读过这些问题,我仍然感到困惑。我想通过用一个例子演示一个问题来弄清楚表单验证应该在哪里处理。
假设我在我的网站上有一个表格,其中有一个字段,有人填写并随后提交。模型希望控制器正确地将该值传递给它,以便在内部处理该值。模型通过函数getInput
接收输入,该函数设置以下规则:
- 输入必须为字符串类型
- 输入必须大于0且小于或等于100个字符
- 输入必须与电子邮件地址的模式匹配
如果这些条件中的任何一个都不满足,我想我应该在getInput
内部抛出一个异常;毕竟,控制器传递的值与模型设置的规则不匹配。
除了上述规则之外,控制器(至少我相当确定这适用于控制器)还必须在脚本继续执行其他三条规则之前,首先验证输入值是否已设置。
现在我的问题是:控制器要验证这(4)条规则中的哪一条,模型要验证哪一条?很明显,控制器知道模型的请求,因此它可以对此进行调整(如果不知道,它可能会面临抛出异常的后果)。另一方面,有几个控制器似乎是多余的,它们都使用模型及其getInput
,验证同一类型的字符串,使其与模型设置的规则相匹配。此外,如果控制器首先验证输入是否具有正确的长度(例如),然后模型立即做同样的事情,那么一旦调用getInput
,似乎会出现更多的冗余。
在这个例子中,控制者和模型可以被视为一种伙伴关系,模型是一个脾气暴躁的完美主义者,他会验证他从控制者那里得到的输入,而不管这些努力为他提供所有欲望的真诚伙伴的行动。但这样的关系不是非常低效吗?
控制器唯一应该关心的是如何将数据传递给模型,以及(可选)如何询问数据是否有效。实际验证应该在模型内部进行,因为:
- 您的模型有责任验证它将要使用的数据
- 您希望能够在不重复自己的情况下重用该模型
- 您希望能够替换模型对象(例如,用一组完全不同的验证规则定义一个子类),而您的控制器不应该在意
这取决于情况。
DRY的最佳情况(不要重复)在模型中验证。
然而。有时,您需要执行的验证可能是针对某个视图量身定制的,尽管这些视图可能有不同的要求,但两者的输入可能对模型有效。
通常,我们的模型基于数据库模式来验证安全输入,而可能通过表格甚至模型上的方法进行验证的控制器可能会关心哪种更具特定目的的验证。
为您的特定目的验证表单输入和验证模型是否正确并不总是一回事。