这个问题主要针对PHP中的Zend,尽管它当然也适用于其他语言和框架,所以我欢迎大家的意见。
我最近才开始使用 Zend 框架,虽然它并不完美,但我用它玩得很开心。 然而,让我发疯的一件事是,我看到的大多数使用 Zend 的人都会执行 v在特殊形式对象中进行验证,而不是在模型中进行验证。 我认为这是不好的做法,因为数据可以通过表单输入之外的其他方式进入系统,这意味着验证器必须弯曲和扭曲才能验证其他输入,或者验证必须在第二个地方完成,并且逻辑重复。
我发现了一些其他帖子和博客,其中有人和我有同样的感觉,但是 Zend 的开发人员做出这个选择是有原因的,而其他人似乎使用它没有问题,所以我想得到一些反馈来自这里的社区。
正如我所说,这主要适用于 Zend,尽管我认为从整体上看待问题很重要,而不是在 Zend 框架的范围内工作,因为 Zend 的设计目的是让您可以使用尽可能多的内容,也可以使用尽可能少的内容,如你所愿。
This question is mainly geared towards Zend in PHP, although it certainly applies to other languages and frameworks, so I welcome everyone's opinion.
I've only recently been using the Zend framework, and while it's not perfect, I have had a pretty good time with it. One thing that drives me crazy, however, is that most of the examples I see of people using Zend do the validation in special form objects, rather than in the model. I think this is bad practice because data can enter into the system in other ways beyond form input, which means that either validators have to be bent and twisted to validate other input, or validation must be done in a second place, and logic duplicated.
I've found some other posts and blogs out there with people who feel the same way I do, but the developers of Zend made this choice for a reason, and other people seem to use it without issue, so I wanted to get some feedback from the community here.
As I said, this mainly applies to Zend, although I think it's important to look at the issue as a whole, rather than working within the confines of the Zend framework, since Zend was designed so that you could use as much, or as little, as you wished.
发布评论
评论(8)
这是一个非 zend 特定的答案,但我认为模型应该对其自身数据的有效性负责。 如果是这种情况,那么验证属于模型中,但是这可能并不总是可以实现,并且可能有必要在视图中执行验证,但是我认为这应该是在模型中执行的验证之外的补充,而不是替代为了它。
仅在视图中进行验证的问题是,在某些时候您可能需要对数据进行另一个视图。 您的网站可能会变得流行,并且客户会要求基于 XML 的 API 来生成他们自己的视图。 那么您是否依赖客户来验证数据?
即使您不必提供 API,一些客户也可能需要足够不同的自定义视图,以保证页面版本完全不同,现在您再次在重复的视图中进行验证。
我认为理想的情况是让您的模型进行验证,但使验证结果可供视图读取并再次渲染页面并显示验证结果。
我认为,如果您想立即将验证数据显示给用户等,那么让视图进行验证是完全合理的,但数据有效性的最终决定应由模型决定。
This is a non-zend specfic answer, however I believe that the model should be responsible for the validity of its own data. If this is the case then the validation belongs in the model, however this may not always be achievable and it may be necessary to perform validation in the view, however I think this should be in addition to the validation performed in the model not a replacement for it.
The problem with only having validation in the view is that at some point you will probably want another view on your data. Your site may become popular and customers are asking for XML based APIs to generate their own views. Do you then rely on the customer to validate the data?
Even if you do not have to provide APIs some customers may want customized views that are sufficiently different to warrant a completely different version of the page, again you now have validation in the views duplicated.
I think the ideal scenario is to have your model do the validation but to make the results of the validation available for the view to read and render the page again with the validation results displayed.
I think it is perfectly reasonable to have the view doing validation if you want to instantly display validation data back to the user etc but the final decision on data validity should rest with the model.
重要的是要记住,与应用程序相关的数据验证并不总是与与数据库模式相关的数据验证相同。
考虑一个简单的注册表单,用户使用用户名和密码创建一个帐户。 您对密码进行验证,因为您希望密码长度为 X 个字符,并包含良好的字符类型(或其他类型)组合。
但这些都与验证数据库插入的数据无关,因为您不会存储纯文本密码 - 您将以某种方式存储它们的哈希值(md5、md5 + salt,等等)。 相反,您可以确保拥有 32 个字符的十六进制字符串,以便它很可能是正确创建的 MD5 哈希值。
此密码示例并不是唯一的场景,只是本主题中用于解释的一个很好的场景。
那么答案是什么呢? 我不认为有任何一劳永逸的解决方案。 有时您会想要(需要?)验证数据两次。 有时您只会在模型中执行一次。 只要尽可能地满足您的应用程序的需求即可。
It's important to remember that data validation which is relevant to an application isn't always the same thing as data validation that's relevant to a database schema.
Consider a simple registration form where a user creates an account with a username and password. You perform validation on the password because you want it to be X number of characters in length and contain a good mix of character types (or whatever).
But none of this is relevant to validate the data for database insertion, because you aren't going to store plain-text passwords - you're going to store a hash of them in some way (md5, md5 + salt, whatever). Instead you might make sure that you have a 32 character hexadecimal string so that it is very likely to be a properly created MD5 hash.
This password example isn't the only scenario, just a good one for explanation here in this topic.
So what's the answer? I don't think there's any one-solution-fits-all. Sometimes you will want (need?) to validate the data twice. Sometimes you'll do it once an only in the Model. Just match it as best as possible to your application's needs.
也许您应该看看 在模型中使用 Zend_Form 作者: Matthew Weier O'Phinney - Zend Framework 的主要开发人员之一 -他对这个问题的看法。
Perhaps you should have a look at Using Zend_Form in Your Models by Matthew Weier O'Phinney - one of the lead-developers of the Zend Framework - for his view on exactly this question.
嗯,验证可以在许多不同的级别上进行,通常没有一个是“最好的”。 当然,模型可以填充非来自表单的无效数据,但我们也可以创建其数据不发送到任何模型的表单。
此外,模型中的直接验证通常不与我们的表单呈现系统集成,如果我们想要显示错误消息并使用用户输入的数据重新填充表单,这会导致问题。
这两种解决方案都有各自的优点和缺点。 如果有一个系统能够确保我们最终必须在某种程度上完成验证,那将是完美的。 如果表单未验证某些数据,则模型会验证某些数据,反之亦然。 不幸的是,我还没有听说过这样的库,但我必须注意框架中的验证器通常是与源无关的。 您可以将 POST 数据传递给它们,但也可以使用从正确解析的 CSV、MYSQL 数据库等检索的信息来完成同样的操作。
Well, the validation can be done at many different levels and usually none of them is "the best". Of course, the model can be populated with invalid data that do not come from the form, but we can also create forms whose data do not go to any model.
Moreover, the direct validation in models is unsually not integrated with our form rendering system, which causes problems if we want to show the error messages and re-populate the form with the user-entered data then.
Both of the solutions have their own pros and cons. It would be perfect to have a system that ensures us that the validation finally must be done at some level. If the form does not validate some data, then the model does and vice versa. Unfortunately, I haven't heard of such library, but I must note that the validators in the frameworks unsually are source-independent. You can pass the POST data to them, but the same can be done with the information retreived from a properly parsed CSV, MYSQL databases, etc.
我不知道 Zend。 但。
您的模型必须接收有效数据。 模型及其方法不应该一次又一次地检查数据。 当然,应该有一些函数可以进行实际验证,并且应该从 gui 验证或其他数据输入位置调用它们。
您在模型方面可以做的最好的事情就是对所有数据调用“断言”,以确保在开发时间验证已取代它。
代码级别越低(UI、模型、实用程序),验证和检查代码应该越少。 这样,同一个验证很可能会被多次调用。
I am not aware of Zend. But.
Your model have to receive valid data. Model and it's methods shouldn't check data again and again. Of course there are should be functions that do actual validation and they should be called from the gui validation or from the other data input place.
The best you can do on your model side is call "Assertions" on all the data to be sure on the development time that validation have been taken its place.
The lower level of the code (UI, model, utils) the less validation and check code should be there. As then there is a big chance that the same validation will be called more then one.
如何将美观验证放入表单中,将业务规则验证放入模型中。
以注册表为例。
该表单将确保电子邮件字段被修剪并包含有效的电子邮件,密码/确认密码字段相同,并且用户选中了“我同意条款”复选框。
注册模型将确保电子邮件尚未被记录在表中,并对密码进行加盐和散列处理。
我通常就是这样分开两者的。
How about putting esthetical validation in the form, and business rules validation in the model.
Take a registration form for example.
The form would assure that the email field is trimmed and contains a valid email, that the password/confirm password field are identical and that the user checked the I Agree to terms checkbox.
The registration model would make sure that the email hasn't been taken yet in the table, would salt and hash the password.
It's how I split the two usually.
用户输入在输入时应该进行验证,因为它特定于输入形式(即,进行一些表单验证 - 确保应该包含数字的文本框是数字)。
业务逻辑可能应该在模型上进行验证,因为它是特定于模型的(即确保他们尚未预订相同的房间或类似的东西)。
在模型级别验证它的问题是模型可能以不同的方式使用。 一种场景的正确输入可能不适合另一种场景的正确输入。
另一个问题是您通常需要一些上下文相关的验证,例如在输入错误的表单控件周围显示一个红色框。
模型或数据库可能会进行一些额外的验证,以确保用户代码没有做完全错误的事情(约束等)。
User input should be validated when it is being inputted because it is specific to the form of entry (ie, do some form validation - make sure text boxes that should have numbers are numbers).
Business logic should probably be validated on the model because it is model specific (ie. make sure they have't already reserved that same room or something like that).
The problem with validating it at the model level is that the model might be used in different ways. Correct input for one scenario may not be correct input for another.
The other issue is that you usually want some context sensitive validation, such as displaying a red box around the form control that has the bad input.
The model or database might do some extra validation to make sure the user code isn't doing something completely wrong (constraints, etc).
Peter Bailey 的密码示例非常好。 用户模型只能验证是否设置了密码(因为它不是以纯文本形式存储,而是以哈希形式存储),而输入验证可以确保原始纯文本密码符合安全要求(字符数,... )。 因此,您需要:模型验证和表单/输入验证,理想情况下作为单独的、可重用的组件,而不是直接在臃肿的控制器操作中。
将输入验证视为白名单验证(“接受已知的良好”),将模型验证视为黑名单验证(“拒绝已知的不良”)。 白名单验证更安全,而黑名单验证可以防止模型层过度受限于非常特定的用例。
无效的模型数据应该总是导致抛出异常(否则应用程序可以继续运行而不会注意到错误),而来自外部源的无效输入值并非意外,而是很常见(除非您的用户从不犯错误)。
另请参阅:https://lastzero.net/2015/11/form -validation-vs-model-validation/
Peter Bailey's password example is excellent. A user model can only validate, if a password was set (because it's not stored as plain text but as a hash) while input validation can ensure, that the original plain text password corresponds to the security requirements (number of characters,...). Therefore you need both: Model validation and form/input validation, ideally as separate, reusable component and not directly in bloated controller actions.
Think of input validation as whitelist validation (“accept known good”) and model validation as blacklist validation (“reject known bad”). Whitelist validation is more secure while blacklist validation prevents your model layer from being overly constrained to very specific use cases.
Invalid model data should always cause an exception to be thrown (otherwise the application can continue running without noticing the mistake) while invalid input values coming from external sources are not unexpected, but rather common (unless you got users that never make mistakes).
See also: https://lastzero.net/2015/11/form-validation-vs-model-validation/