在PHP模型中验证的常见模式有哪些?

时间:2009-11-14 11:10:50

标签: php design-patterns

目前,我创建了一个对象并使用其setter来设置从客户端收到的get / post数据。并在调用save()函数之前调用validate():

//member registration
$m=new Member();
$m->setName($_POST['name']);
$m->setBirthDate($_POST['birthdate']);
$m->setAddress($_POST['address']);

$arrOfErrMsgs=$m->validate();

if(!empty($arrOfErrMsgs)){
//echo some error messages to client or redirect to a page that shows the error
exit();
}

$saveSuccess=$m->save(); //to be safe, inside this save function, it will also call validate() again before saving, so that even someone forgot to call validate() before calling save() by mistake, no dirty data will appear in the database 

if($saveSuccess){
//echo a success message to client or redirect to a success page

}else{
//echo save failed message to client (normally this should not happen unless db server suddenly fails)
}

exit();

虽然这有效,但应该有一些替代方案。例如,也许某些验证可以在setter中完成。

我想知道PHP中模型中验证的模式最常见?

4 个答案:

答案 0 :(得分:2)

控制器应该验证,模型不应该处理任何不可信的数据。

答案 1 :(得分:2)

我不推荐这种验证模型的方法。

首先,让控制器验证输入,确保它应该是一个字符串,应该是一个整数,依此类推。但不是商业逻辑。

当您创建新成员时,我建议通过构造函数传递所有信息。这样构造函数可以检查OVERALL模型的一致性,而setter方法应该对它们负责的每个数据进行一致性检查。

例如,如果您有另一条信息,例如firstHeardOf(他们第一次听说他们成为其成员的任何网站),那么设定者应该确保它是一个有效的日期,并且它是在出生日期之后,至少。这会创建方法的排序问题,并且要求以特定顺序调用方法不是好习惯,而是可以使用构造函数来保证调用的顺序。

save方法现在只是一个简单的方法,它保存了数据,而且为什么它还有其他任何责任。最多应该仔细检查构造的成员是否仍然有效,这是您可能希望将构造函数验证代码拉入私有/受保护的验证方法并在两个地方调用它的地方。

关于责任的快速说明,以及他们如何在这里打破,至少在我的脑海里:

  • 构造函数负责创建有效/正确初始化的Member对象
  • 设置者负责在数据的成员对象中设置有效数据
  • save方法负责保存有效的成员对象

答案 2 :(得分:1)

我认为这是执行业务验证的完美方式。如果数据无效,您的save()方法可能会返回带有错误消息的字符串,否则为true(保存冗余validate()调用)。这是我目前采用的方法 - 尽管它实际上取决于您希望如何设计API。只要它是可预测的并且有意义。

与erenon评论一样,该模型不应该执行低级验证,例如检查整数,日期格式,恶意代码等 - 这些属于其他地方(例如Zend_Form)。但是对于像member must be over 21 years old这样的业务验证,我没有发现问题。

答案 3 :(得分:1)

<?php

abstract class Model {

    protected $errors = array();

    public function validate() {
        // Implement validation logic, overriden in subclasses
    }

    public function isValid() {
        $this->validate();
        return empty($this->errors);
    }

    public function save() {
        if (!$this->isValid()) {
            return false;
        }

        // Perform the saving operation
    }
}

class Member extends Model {

    // setters and getters and constructor

    public function validate() {
        if (empty($this->name)) {
            $this->errors[] = 'name can not be empty';
        }
    }
}

$member = new Member(array(
    'name' => 'Hanse'
));

if ($member->save()) {
    // Print success messages
} else {
    // Print error messages
    print_r($member->getErrors());
}

我更喜欢上面代码的方法。为您提供干净灵活的API。