域对象:setter和getter还是只是公共属性?

时间:2014-06-12 07:58:31

标签: php validation getter-setter domain-object

我应该在设置域对象属性时验证它吗?

在这个例子中,我从模型层获得了一个用户域对象,目前我只是在设置属性之前验证传入参数的类型和/或格式,因为我没有任何线索在涉及域对象时应该验证什么。一些例子可以帮助我理解它。

我应该如何验证域对象属性,还是不应该验证它们?

在后一种情况下,我可以删除每个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;
        }
    }
}

2 个答案:

答案 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个字符之间”。第二 - 域特定验证,例如,“电子邮件必须是唯一的”。域验证可能很昂贵,并且通常需要许多支持类(服务,数据映射器,数据库适配器等)。