【问题标题】:Should validation be done in Form objects, or the model?是否应该在 Form 对象或模型中进行验证?
【发布时间】:2009-03-18 20:25:15
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: php zend-framework validation zend-validate


    【解决方案1】:

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

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

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

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

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

    【讨论】:

      【解决方案2】:

      请务必记住,与应用程序相关的数据验证并不总是与与数据库架构相关的数据验证相同。

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

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

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

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

      【讨论】:

        【解决方案3】:

        也许您应该看看Matthew Weier O'PhinneyUsing Zend_Form in Your Models - Zend 框架的主要开发人员之一 - 了解他对这个问题的看法。

        【讨论】:

          【解决方案4】:

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

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

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

          【讨论】:

            【解决方案5】:

            我不知道 Zend。但是。

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

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

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

            【讨论】:

              【解决方案6】:

              如何将美学验证放在表单中,将业务规则验证放在模型中。

              以注册表为例。

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

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

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

              【讨论】:

                【解决方案7】:

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

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

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

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

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

                【讨论】:

                  【解决方案8】:

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

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

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

                  另请参阅:https://lastzero.net/2015/11/form-validation-vs-model-validation/

                  【讨论】:

                    猜你喜欢
                    • 2011-01-22
                    • 2011-04-12
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-09-24
                    • 2011-01-16
                    • 2021-10-27
                    相关资源
                    最近更新 更多