免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1619 | 回复: 0
打印 上一主题 下一主题

如何使用模型的自动验证 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-04-12 09:50 |只看该作者 |倒序浏览

对于一个业务对象,确保数据的有效性是基本要求。QeePHP 的 ActiveRecord 实现为此提供了全面的自动化验证功能。
按照验证规则进行验证
打开用代码生成工具生成的模型源代码,可以看到一大段的验证规则。这些验证规则都是根据数据库表结构自动生成的。我们可以对这些规则进行定制,以便满足我们的要求。
就拿最常见的“用户”来说,通常要求用户名必须至少有 4 个字符,而密码有至少 6 个字符。这些验证我们都可以让 QeePHP 自动完成。
'validation' => array(
    'username' => array(
        array('not_empty', '登录用户名不能为空'),
        array('min_length', 4, '登录用户名最少要有 4 个字符'),
        array('max_length', 30, '登录用户名不能超过 30 个字符'),
        array('is_alpha_number', '登录用户名只能是 26 个字母加数字组成'),
    ),
    'password' => array(
        array('not_empty', '登录密码不能为空'),
        array('min_length', 6, '登录密码最少要有 6 个字符'),
        array('max_length', 64, '登录密码不能超过 64 个字符'),
    ),
    'email' => array(
        array('not_empty', '电子邮件不能为空'),
        array('max_length', 100, '电子邮件不能超过 100 个字符'),
        array('is_email', '必须是有效的电子邮件地址'),
    ),
),
上面的验证规则很容易懂,就不一一解释了。
只要我们定义好验证规则,在将一个“用户”模型对象存入数据库之前,就会按照这些规则对模型数据进行验证。如果验证失败,将会抛出一个 QDB_ActiveRecord_Validate_Exception 异常。这个异常包含了被验证的对象,以及没有通过验证的规则和错误信息。所以我们捕获这个异常就可以获得详细的错误信息了。
控制器代码片段:
function actionCreate()
{
    try {
        $user = new User($_POST);
        $user->save();
      
        // 保存成功,重定向浏览器到登录页面
        return new QResponse_Redirect($this->url->make('members', 'login'));
    } catch (QDB_ActiveRecord_Validate_Exception $ex) {
        QDebug::dump($ex->validate_error);
    }
}
上面的代码没有对验证失败做任何处理,仅仅是显示出 QDB_ActiveRecord_Validate_Exception 异常的 $validate_error 属性。这个属性实际上就是没有通过验证的规则及其错误信息。
Array
(
    [username] => Array
        (
            [notEmpty] => 登录用户名不能为空
            [minLength] => 登录用户名最少要有 4 个字符
            [isAlphaNumber] => 登录用户名只能是 26 个字母加数字组成
        )
    [password] => Array
        (
            [notEmpty] => 登录密码不能为空
            [minLength] => 登录密码最少要有 6 个字符
        )
    [email] => Array
        (
            [notEmpty] => 电子邮件不能为空
            [isEmail] => 必须是有效的电子邮件地址
        )
)
有了这些数据,要在界面上显示错误信息就简单了。下面是一段模板代码:
tr>
    td width="220" align="right">span class="note">*/span> 用户名:/td>
    td>?php $this->html->textbox('username', $form['username'], 30, 20, 'class="form_field"'); ?>/td>
  /tr>
  tr>
    td align="right"> /td>
    td>span class="note">*/span> a href="url->make('members', 'index'); ?>">我已经注册有账户了/a>/td>
  /tr>
  ?php if (!empty($error['username'])): ?>
  tr>
    td width="220" align="right"> /td>
    td>span class="error">! ?php echo h(implode(', ', $error['username'])); ?>/span>/td>
  /tr>
  ?php endif; ?>
实际效果如下:

以后,当使用 QForm 来处理表单时,连模板代码都不用写了,QeePHP 会自动搞定这些琐碎的工作。
用回调方法验证数据
QeePHP 已经内置了不少验证规则,但是实际开发中肯定是不够用的。而且有些验证不是简单的比较操作能完成的。所以 QeePHP 还允许以回调函数的方式来书写验证规则。
假设“用户”对象有一个验证规则是要求密码必须是由特定规则组成的(例如:2 个字母 + 4 个数字 + 3 个字母),那我们将密码的验证规则改为:
'password' => array(
        array('not_empty', '登录密码不能为空'),
        array('min_length', 6, '登录密码最少要有 6 个字符'),
        array('max_length', 64, '登录密码不能超过 64 个字符'),
        array(array('validatePassword'), '登录密码必须由 2 个字母 + 4 个数字 + 3 个字母组成'),
    ),
然后再为“用户”类添加一个静态方法
static function validatePassword($password)
{
    // 傻傻的验证规则 ^_^
    if (strlen($password) != 7) { return false; }
    if (preg_match('/[^a-z]/', substr($password, 0, 2))) { return false; }
    if (preg_match('/[^0-9]/', substr($password, 2, 4))) { return false; }
    if (preg_match('/[^a-z]/', substr($password, 6, 3))) { return false; }
    return true;
}
这样一来,保存用户对象时,就会调用 validatePassword() 对密码进行验证了。
当然,这里仅仅是举例。实际上这个验证规则可以通过正则表达式来完成:
'password' => array(
        array('not_empty', '登录密码不能为空'),
        array('min_length', 6, '登录密码最少要有 6 个字符'),
        array('max_length', 64, '登录密码不能超过 64 个字符'),
        array('regexp', '/[a-z]{2}[0-9]{4}[a-z]{3}/i', '登录密码必须由 2 个字母 + 4 个数字 + 3 个字母组成'),
    ),
利用验证事件进行验证
有时候,确定对象是否有效,需要根据对象的多个属性来判断,此时就没法使用上面的两种方法了。好在 QeePHP 提供了 6 个验证事件,分别是:
beforeValidation
在对模型开始验证之前调用该事件
afterValidation
在对模型的验证完成之后调用该事件
beforeValidationOnCreate
在对模型开始验证之前调用该事件,但仅仅出现在保存对象需要在数据库中新建记录时
afterValidationOnCreate
在对模型的验证完成之后调用该事件,但仅仅出现在保存对象需要在数据库中新建记录时
beforeValidationOnUpdate
在对模型开始验证之前调用该事件,但仅仅出现在保存对象需要更新数据库中的已有记录时
afterValidationOnUpdate: 更新记录验证之后
在对模型的验证完成之后调用该事件,但仅仅出现在保存对象需要更新数据库中的已有记录时
根据上面的规则,自动验证引发的事件有两个路径。
保存新建的对象到数据库(需要创建记录):

  • beforeValidation
  • beforeValidationOnCreate
  • afterValidationOnCreate
  • afterValidation

保存查询出来的对象到数据库(仅仅更新数据库中已有的记录):

  • beforeValidation
  • beforeValidationOnUpdate
  • afterValidationOnUpdate
  • afterValidation

要拦截某个事件,只需要在对象中添加如下格式的方法(注意方法名和事件之间的对应关系):
protected function beforeValidation()
{
    .....
    parent::beforeValidation();
}
事件方法中,一定要记得调用父类的同名方法。这样在类的继承体系中才能确保每个层次的验证都得以进行。
通常,如果仅仅是做单纯的数据验证,而不改变对象的属性,那么就使用 afterValidation() 方法。如果要在 QeePHP 内置的验证执行之前改变对象属性,就应该使用 beforeValidation() 方法。只要多加摸索和实验,就能选择合适的验证方法。
例如通常不允许创建相同用户名的用户,因此我们可以在用户对象中添加一个 afterValidation() 方法,处理这种情况:
function afterValidation()
{
    $row = User::find('username = ?', $this->username)->count()->query();
    if (!empty($row['row_count']) && $row['row_count'] > 0) {
        // 找到同名用户,抛出异常
        $error = array('username' => array('您提供的用户名 ' . $this->username . ' 已经被使用了,请重新选择一个用户名'));
        throw new QDB_ActiveRecord_Validate_Exception($this, $error);
    }
}
这段代码会在对象完成基本验证后,保存到数据库之前调用。当发现同名用户时,抛出的异常会被控制器捕获,并显示在界面上。
实际上,QeePHP 的 ActiveRecord 提供了一个名为 acluser 的行为插件,已经内置了此功能,所以我们就不需要书写上述的代码了。但是知道了其中的原理,可以便于我们更严格的处理对象数据有效性问题。
合理利用 QeePHP 为 ActiveRecord 提供的自动验证机制,可以将以前原本写在控制器或其他地方的一大堆验证代码都迁移到模型中。从而更好的应用面向对象设计原则。实际上,只有将验证规则写在模型中,才能真正保证模型数据的有效性。
更多信息,请访问 FleaPHP/QeePHP 开源开发框架官方网站:
http://www.fleaphp.org/



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/66280/showart_527920.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP