验证域对象设置器中的表单输入?

时间:2013-02-23 13:20:39

标签: php oop model-view-controller model validation

由于我开始学习MVC,我总是在我的控制器中验证我的表单数据,这是我在浏览CodeIgniters代码时习惯的习惯,但我已经了解到它做某些操作的方式不是最好的,它只是完成工作。

域对象是否应验证所有表单数据?如果是这样的话,应该在这样的设置者中完成

public function setFirstName($firstName) {

    // Check if the field was required
    if(!$firstName) {
        throw new InvalidArgumentException('The "First name" field is required');
    }

    // Check the length of the data
    // Check the format 
    // Etc etc
}

另外,例如,如果我正在处理基本用户注册,我的User类没有$confirmPassword属性,所以我不会这样做

$user->setConfirmPassword($confirmPassword);

检查输入的两个密码是否相同的一种方法是设置$password并执行类似

的操作
$user->setPassword($password);
if(!$user->matchPassword($confirmPassword)) {
    throw new PasswordsNotEqualException('Some message');
}

这可以在我想到的服务层中完成吗?

任何帮助我正确指导的建议都会很棒。感谢。

2 个答案:

答案 0 :(得分:3)

  

域对象是否应验证所有表单数据?如果是这样   应该在像这样的设置者中完成

IMO你应该只创建有效的对象,而最好的方法是在创建对象的方法中进行这些检查。

假设无法更改用户的名字,您将在创建用户时验证该名称。这样,你就忘了了setter,因为你不再需要了它。

在某些情况下,您可能希望更改属性,并且您也需要对其进行验证(因为如果出现这种情况,该更改可能导致将有效对象形成无效对象)。

  

检查输入的两个密码是否相等的一种方法是   设置$密码并执行类似......

的操作

你可以用同样的方式处理这个:拥有一个Password对象,在创建时检查密码和确认。您拥有一个有效的密码实例,您可以使用它知道它通过了您指定的所有验证。

<强>参考

这些设计原则(从一开始就完整有效的对象等)来自Hernan Wilkinson的“巴塔哥尼亚背后的设计原则”。请务必查看ESUG 2010 Videopresentation slides

我最近回答了另一个关于验证属性的问题,我认为您可以派上用场:https://stackoverflow.com/a/14867390/146124

干杯!

答案 1 :(得分:3)

TL; DR

不,设置者不应该验证数据。并且 nick2083 是完全错误的。

更长的版本......

根据Tim Howard提供的定义 [source] domain objects可以验证它们包含的域信息的状态。这基本上表明,对于您实际拥有域对象,所述对象需要能够自我验证。

何时验证

你基本上必须选择:

  • 在每个setter中验证
  • 有一种验证整个对象的方法

如果验证是setter的一部分,那么有一个主要缺点:setter的顺序很重要。

  

示例:让我们假设您正在制作一份处理人寿保险的应用程序。很可能,当政策被触发(被保险人死亡)时,您将拥有一个域对象,其中包含被保险人和获得保险费的人。您必须确保收件人和被保险人不是同一个人。但是没有规则来管理执行setter的顺序。

如果域对象中有两个或多个参数,必须相互验证,则实现会变得有点模糊。最可行的解决方案是检查何时分配了所有参数,但此时您已经失去了嵌入式验证的好处:代码的执行已经超过了无效数据的来源。

如果参数B大于21且C已经设置,那么你将如何处理域对象的有效状态没有参数A set的情况?

  

结论: setter中的验证只是可行的解决方案,当你有非常简单的域对象时,没有纠结的验证规则。