我应该在设置域对象属性时验证它吗?
在这个例子中,我从模型层获得了一个用户域对象,目前我只是在设置属性之前验证传入参数的类型和/或格式,因为我没有任何线索在涉及域对象时应该验证什么。一些例子可以帮助我理解它。
我应该如何验证域对象属性,还是不应该验证它们?
在后一种情况下,我可以删除每个setter和getter,只需将域对象属性公开,这样我就可以直接与它们进行交互。
class User
{
private $id;
private $firstname;
private $lastname;
private $email;
private $password;
private $registerDate;
public function setId($id)
{
if (is_int($id)) {
$this->id = $id;
} else {
throw new Exception('Parameter must be an integer.');
}
}
public function setFirstname($firstname)
{
if (is_string($firstname)) {
$this->firstname = $firstname;
} else {
throw new Exception('Parameter must be a string.');
}
}
//{ etc setters }
public function __get($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
}
答案 0 :(得分:0)
在动态的弱类型语言中检查原始类型对我来说似乎有点过头了99%的时间。如果你的$firstname
是一个正确的字符串真的没关系,它会在需要时隐式转换为一个字符串。
但是,有时检查作为参数传递的原语的值(而不是其类型,请注意)是否符合某些特定的业务逻辑约束是否有意义:
function squareRoot($number) {
if(!is_numeric($number) || $number < 0)
throw new \InvalidArgumentException("Positive number expected.");
return sqrt($number);
}
那就是说,在绝对必要时我只会使用这种beaurocracy。如果有人想将非数字字符串传递给名为setNumber($number)
的方法,并且文档类型$number
是一个数字,那么如果结果中发生了不好的事情,那就是他的问题。
如果方法需要特定类型的对象(或实现特定接口)作为参数,请改用类型提示:
function foo(BarObject $bar) {
// ...
}
这也适用于数组:
function doStuffWithArray(array $a) {
// ...
}
有趣的是,没有类型提示允许实现\ArrayAccess
接口的数组和对象,但这只是许多PHP怪癖之一。
答案 1 :(得分:0)
我的建议是将验证逻辑从实体移到类,它们会持久化它们,无论是数据映射器,存储库还是其他东西。或者更好的是,为每个实体类型/聚合根分开验证器类。
为什么呢?分离关注点。
让我们考虑验证。我看到两种验证器。第一种类型/范围检查,例如,“用户名必须是字符串,并且在5-50个字符之间”。第二 - 域特定验证,例如,“电子邮件必须是唯一的”。域验证可能很昂贵,并且通常需要许多支持类(服务,数据映射器,数据库适配器等)。