如何在数据库操作之前验证域对象数据?

时间:2012-08-16 19:08:17

标签: php model-view-controller domain-object

我将使用一个抽象(和简单)示例来说明问题:CarDomainObject,如下所示:(成员旁边列出了示例mysql数据类型)

class carDomainObject extends DomainObjectAbstract {

    public $uid;                //int
    public $make;               //varchar
    public $model;              //varchar
    public $productionDate;     //timestamp
    public $doors;              //tinyint

}

class DomainObjectAbstract {

    public function setData(array $data=array())
    {
        foreach ($data as $key => $value)
        {
            if ( ! empty($key))
            {
               $this->$key = $value;
            }
        }
    }

    //if $val is not passed, checks for ANY set value,
    //  else checks that $this->$val is set (dirty)
    public function isDirty($val=false)
    {
        foreach(get_object_vars($this) as $key => $property)
        {
            if( ! is_null($property) && ( ! $val || $key == $val))
            {
                return true;
            }
        }
        return false;
    }

}

假设我们想要将新车插入数据库,因此我们设置了一些值:

$carDomainObject->setData(array('make' => 'ford', 'model' => 'taurus'));

现在,未设置的值仍为NULL,适用于isDirty()方法。这个模式不起作用的是将一个对象(如上所述初始化,只有某些值)插入到数据库中,其中NULL可能不是该列的有效值。

所以,我的问题是:我们如何验证域对象中的每个数据块是否已准备好插入数据库?我看到的方式有几个选择:

  1. 如果我们使用成员变量的默认值(0表示int,''表示varchar等),那么isDirty()会变得更复杂,因为null检查是不够的。但是,检查数据是否能够插入变得微不足道,因为可以插入默认值而不会出现问题

  2. 如果我们坚持使用NULL作为默认值,那么isDirty()保持相当简单,但确保数据为数据库做好准备会变得复杂。

  3. 单独验证每个变量,根据DO的不同,这会很快变得难看。

  4. 在MySQL中使用默认值 - 对我来说不是一个真正的选项,但通常是一个有效的选项

1 个答案:

答案 0 :(得分:0)

  

我觉得你接受了this post的部分内容,但误解了问题,那就解决了。

在保存之前,您似乎试图确定模型是否有效。但是你的结构存在缺陷:

  1. 如果您使用单一设置器,那么当您尝试添加越来越多的条件时,此设置器的复杂性会增加。此外,通过避免为每个参数单独设置,您将失去实际验证参数的能力。

    当您为域对象设置无效值时,它应该创建内部错误状态。

  2. 您的验证假设所有值必须不为null。如果他们可以NULL怎么办?如果值通过业务规则确认,则应检查参数的验证,而不是使用数据库设置的约束。

  3. 当mapper尝试在数据库中存储无效值时,会导致错误。如果您使用正确设置PDO实例,它将引发异常。您如何处理该异常,那么这是您的选择。域对象不负责数据库中的数据完整性。