4

这个问题主要针对PHP中的Zend,当然也适用于其他语言和框架,所以欢迎大家提出意见。

我最近才使用 Zend 框架,虽然它并不完美,但我玩得很开心。然而,让我发疯的一件事是,我看到的大多数使用 Zend 的人的例子都是在特殊形式的对象中进行验证,而不是在模型中。我认为这是不好的做法,因为数据可以通过表单输入以外的其他方式进入系统,这意味着验证器必须弯曲和扭曲才能验证其他输入,或者验证必须在第二个地方完成,并且逻辑重复。

我发现了一些与我有同样感受的人的其他帖子和博客,但是 Zend 的开发人员做出了这个选择是有原因的,其他人似乎毫无问题地使用它,所以我想得到一些反馈从这里的社区。

正如我所说,这主要适用于 Zend,尽管我认为从整体上看待问题很重要,而不是在 Zend 框架的范围内工作,因为 Zend 的设计目的是让您可以尽可能多地使用或尽可能少地使用,如你所愿。

4

8 回答 8

3

好吧,验证可以在许多不同的级别上完成,通常它们都不是“最好的”。当然,模型可以填充不是来自表单的无效数据,但我们也可以创建其数据不进入任何模型的表单。

此外,模型中的直接验证通常没有与我们的表单呈现系统集成,如果我们想要显示错误消息并使用用户输入的数据重新填充表单,就会出现问题。

这两种解决方案都有各自的优缺点。如果有一个系统可以确保我们最终必须在某个级别完成验证,那将是完美的。如果表单不验证某些数据,那么模型会验证,反之亦然。不幸的是,我还没有听说过这样的库,但我必须指出,框架中的验证器异常地是与源无关的。您可以将 POST 数据传递给它们,但同样可以对从正确解析的 CSV、MYSQL 数据库等中检索到的信息进行处理。

于 2009-03-18T20:46:08.807 回答
3

重要的是要记住,与应用程序相关的数据验证并不总是与与数据库模式相关的数据验证相同。

考虑一个简单的注册表单,其中用户使用用户名和密码创建一个帐户。您对密码执行验证是因为您希望它的长度为 X 个字符并且包含字符类型(或其他)的良好组合。

但这与验证数据库插入的数据无关,因为您不会存储纯文本密码 - 您将以某种方式存储它们的哈希值(md5、md5 + salt 等)。相反,您可以确保您有一个 32 个字符的十六进制字符串,以便它很可能是正确创建的 MD5 哈希。

此密码示例不是唯一的场景,只是本主题中的一个很好的解释。

那么答案是什么?我不认为有任何一种万能的解决方案。有时您会想要(需要?)两次验证数据。有时你会在模型中只做一次。尽可能将其与您的应用程序的需求相匹配。

于 2009-03-18T21:00:47.490 回答
3

这是一个非 zend 特定的答案,但是我相信模型应该对其自身数据的有效性负责。如果是这种情况,则验证属于模型,但这可能并不总是可以实现,并且可能需要在视图中执行验证,但是我认为这应该是模型中执行的验证的补充,而不是替代为了它。

仅在视图中进行验证的问题在于,在某些时候您可能需要另一个视图来查看您的数据。您的站点可能会变得流行,并且客户要求使用基于 XML 的 API 来生成他们自己的视图。然后,您是否依赖客户来验证数据?

即使您不必提供 API,一些客户可能希望自定义视图足够不同以保证页面的完全不同版本,您现在再次在重复的视图中进行验证。

我认为理想的情况是让您的模型进行验证,但使验证结果可用于视图读取并再次呈现页面并显示验证结果。

如果您想立即将验证数据显示给用户等,我认为让视图进行验证是完全合理的,但数据有效性的最终决定应取决于模型。

于 2009-03-18T21:21:02.920 回答
3

也许您应该看看Matthew Weier O'Phinney(Zend 框架的主要开发人员之一)在您的模型中使用 Zend_Form 以了解他对这个问题的看法

于 2009-03-19T10:59:44.073 回答
0

我不知道 Zend。但。

您的模型必须接收有效数据。模型及其方法不应该一次又一次地检查数据。当然应该有一些函数可以进行实际验证,它们应该从 gui 验证或其他数据输入位置调用。

您可以在模型方面做的最好的事情是对所有数据调用“断言”,以确保在开发时间验证已被取代。

代码(UI、模型、实用程序)的较低级别应该存在较少的验证和检查代码。那样的话,同样的验证很有可能会被调用不止一个。

于 2009-03-18T20:34:07.150 回答
0

将美学验证放在表单中,将业务规则验证放在模型中怎么样。

以注册表为例。

该表单将确保电子邮件字段被修剪并包含有效的电子邮件,密码/确认密码字段相同,并且用户选中了我同意条款复选框。

注册模型将确保电子邮件尚未在表格中被占用,并对密码进行加盐和哈希处理。

这就是我通常将两者分开的方式。

于 2009-03-19T00:35:51.140 回答
0

用户输入应在输入时进行验证,因为它特定于输入形式(即,进行一些表单验证 - 确保应该有数字的文本框是数字)。

业务逻辑可能应该在模型上进行验证,因为它是特定于模型的(即确保他们尚未预订同一个房间或类似的东西)。

在模型级别验证它的问题是模型可能以不同的方式使用。一种情况的正确输入可能不是另一种情况的正确输入。

另一个问题是您通常需要一些上下文相关的验证,例如在输入错误的表单控件周围显示一个红色框。

模型或数据库可能会做一些额外的验证,以确保用户代码没有做完全错误的事情(约束等)。

于 2009-03-19T14:09:19.813 回答
0

Peter Bailey 的密码示例非常出色。用户模型只能验证,如果设置了密码(因为它不是作为纯文本存储,而是作为哈希存储),而输入验证可以确保原始纯文本密码符合安全要求(字符数,... )。因此,您需要:模型验证和表单/输入验证,最好是作为单独的、可重用的组件,而不是直接在臃肿的控制器操作中。

将输入验证视为白名单验证(“接受已知良好”),将模型验证视为黑名单验证(“拒绝已知不良”)。白名单验证更安全,而黑名单验证可防止您的模型层过度受限于非常特定的用例。

无效的模型数据应始终导致抛出异常(否则应用程序可以继续运行而不会注意到错误),而来自外部来源的无效输入值并非意料之外,而是很常见(除非您的用户从不犯错误)。

另见:https ://lastzero.net/2015/11/form-validation-vs-model-validation/

于 2015-11-15T10:41:32.073 回答