Php 在模型/视图/控制器模型中进行验证的最佳位置?

Php 在模型/视图/控制器模型中进行验证的最佳位置?,php,model-view-controller,validation,design-patterns,forms,Php,Model View Controller,Validation,Design Patterns,Forms,我正在从事一个广泛使用MVC设计模式的PHP项目。我希望将验证添加到表单中,并对验证的正确位置感到好奇 由于表单的生成方式,在视图组件中对回发数据的验证要简单得多,重复性也更少。让视图验证响应数据是可以接受的,还是应该在控制器甚至模型中实现 好处是什么?如果您在客户端验证数据(即Javascript验证),这绝对不够,而且根本不安全,那么您应该在视图中实现它 如果您在服务器端验证数据,并且您的验证不需要应用程序业务逻辑(即,您没有检查用户帐户中是否有足够的信用),那么您应该在控制器中进行验证 如

我正在从事一个广泛使用MVC设计模式的PHP项目。我希望将验证添加到表单中,并对验证的正确位置感到好奇

由于表单的生成方式,在视图组件中对回发数据的验证要简单得多,重复性也更少。让视图验证响应数据是可以接受的,还是应该在控制器甚至模型中实现


好处是什么?

如果您在客户端验证数据(即Javascript验证),这绝对不够,而且根本不安全,那么您应该在视图中实现它

如果您在服务器端验证数据,并且您的验证不需要应用程序业务逻辑(即,您没有检查用户帐户中是否有足够的信用),那么您应该在控制器中进行验证

如果验证需要业务逻辑,则在模型内部实现它,并通过控制器调用它

回发验证是不好的,因为它会带来很大的压力和延迟,唯一的优势是程序员(不需要说明)


大多数验证都可以使用regex,它在PHP和JS上的语法(几乎)相同。

正确的验证位置是模型

这非常有意义,因为您正在对数据进行验证,而数据正是模型所表示的。就CRUD更新而言,应该始终以某种方式使用模型

  • 如果您正在更改来自 视图中,应该有验证 正在检查

  • 如果您有控制器正在更改 数据,您应该进行验证 正在检查

  • 最后,如果你有 模型本身改变了数据,你 应该仍然有验证

实现此状态的唯一方法是将验证放入模型中

由于性能和更快的响应,在模型中实现验证后,您应该尝试添加某种类型的客户端(JS)以立即通知最终用户


验证始终与数据有关。为什么要验证数据?因此,您可以保持存储信息的完整性。在模型级别进行验证可以使数据在理论上始终正确。这总是必要的。从那里,您可以在业务逻辑和客户端中添加额外的验证,以使您的应用程序更加用户友好。

模型中的验证似乎是最常见的方法(您最终会得到类似于
$obj->isValid()
)的结果),这适用于许多情况

但是,根据您的用例,可能有很好的理由在模型之外执行验证,或者使用单独的验证代码,或者在控制器中执行验证,等等:

  • 如果大部分整体验证问题涉及模型无法访问的信息(例如,如果管理员用户可以执行常规用户无法执行的转换,或者某些属性在特定日期后无法更改),那么您可能希望在同一位置检查所有这些约束
  • 在为测试构建对象时,应用非常宽松的验证规则也可能是方便或必要的。(一个“购物篮”对象通常可能需要一个关联的用户,而该用户又需要一个有效的电子邮件地址等。在购物篮单元测试中,100%有效的购物篮对象可能不方便构造。)
  • 由于历史原因,验证规则可能会发生变化(例如,在以前不需要“性别”的情况下强制执行“性别”),因此最终可能会出现需要区别对待的不同版本的数据。(不同的验证规则也可能适用于批量数据导入。)
  • 如果验证非常复杂,您可能希望根据对调用方最有用的内容提供不同的错误消息(或者根本不提供错误消息)。在其他情况下,
    true
    false
    可能是所有必要的

可以通过模型的
isValid()
方法的参数来处理这些不同的用例,但是随着验证样式数量的增加,这种方法变得越来越难以处理。(我确实认为几乎可以保证,一个“一刀切”的
isValid()
方法最终将证明不足以用于大多数非琐碎的项目。)

不要将清理发布值与验证混为一谈。您应该获取发布的值,并通过从控制器内的值中删除任何恶意元素来清除这些值。然后将数据发送到要验证预期值或格式的模型。通过将这些操作分为两个过程,可以降低恶意代码实现的风险。如果您使用的是“不信任任何人输入”策略,则此方法效果良好;了解一些程序员可能会变得马虎或懒惰。另一个积极的方面是防止您的模型变得臃肿和过度工作,如果是这样的话,那么请使用模型助手来完成这些脏活。这种方法还有助于平衡应用程序负载并提高性能

我被教导使控制器尽可能轻。在我看来,验证是业务逻辑的一部分……在您的示例中,重复的用户名是应用程序逻辑的一部分。但用户名中的无效字符可以在controller.controllers上检查,但由于验证是强制性的,所以不能跳过。点亮控制器意味着不在其中放置任何逻辑或视图。MVC中的控制器是表示层的一部分。他们不应该对如何执行数据验证有任何线索,这是模型层的责任,不是这样的。你的意思是UI不应该告诉用户他们是否键入了名称而不是数字?它与应用程序的业务逻辑无关。这更像是一个演示问题。一