PHP YII框架开发小技巧之模型(models)中rules自定义验证规则


Posted in PHP onNovember 16, 2015

YII的models中的rules部分是一些表单的验证规则,对于表单验证十分有用,在相应的视图(views)里面添加了表单,在表单被提交之前程序都会自动先来这里面的规则里验证,只有通过对其有效的限制规则后才能被提交,可以很有效地保证表单安全和信息的有效性。还是给大家具体说明一下:

以下是视图(views)部分的简单代码:

<?php $form=$this->beginWidget('CActiveForm', array( 
  'id'=>'tag-form', 
  'enableAjaxValidation'=>false, 
)); ?> 
  <div class="row"> 
    <?php echo $form->labelEx($model,'tagname'); ?> 
    <?php echo $form->textField($model,'tagname',array('size'=>20,'maxlength'=>32)); ?> 
  </div> 
  <div class="row"> 
    <?php echo $form->labelEx($model,'tagtype'); ?> 
    <?php echo $form->radioButtonList($model,'tagtype'array(1=>"普通TAG",2=>"系统默认TAG"),array('separator'=>'','labelOptions'=>array('class'=>'tagtypelabel'))); ?> 
  </div> 
  <?php echo $form->errorSummary($model); ?> 
  <div class="row buttons"> 
    <?php echo CHtml::submitButton($model->isNewRecord ? '添加' : '修改'); ?> 
  </div> 
<?php $this->endWidget(); ?>

模型(models)中rules部分的简单代码:

public function rules() 
{ 
  return array( 
    array('tagname,tagtype', 'required'), 
    array('tagtype', 'numerical', 'integerOnly'=>true), 
    array('tagname', 'length', 'max'=>32), 
    array('tagname', 'match', 'pattern'=>'/^[\x{4e00}-\x{9fa5}A-Za-z0-9]+$/u', 
        'message'=>'标签不合法,必须为汉字、字母或者数字!'), 
    array('tagname', 'checktagname', 'on'=>'create,update'),//插入TAG时检查是否已经存在该tag 
    array('tagid, tagname, tagtype', 'safe', 'on'=>'search'), 
  ); 
}

系统默认有这些验证规则:

boolean : CBooleanValidator 的别名, 确保属性的值是CBooleanValidator::trueValue 或 CBooleanValidator::falseValue . 
captcha : CCaptchaValidator 的别名,确保了特性的值等于 CAPTCHA 显示出来的验证码. 
compare : CCompareValidator 的别名, 确保了特性的值等于另一个特性或常量. 
email : CEmailValidator 的别名,确保了特性的值是一个有效的电邮地址. 
default : CDefaultValueValidator 的别名, 为特性指派了一个默认值. 
exist : CExistValidator 的别名, 确保属性值存在于指定的数据表字段中. 
file : CFileValidator 的别名, 确保了特性包含了一个上传文件的名称. 
filter : CFilterValidator 的别名, 使用一个filter转换属性. 
in : CRangeValidator 的别名, 确保了特性出现在一个预订的值列表里. 
length : CStringValidator 的别名, 确保了特性的长度在指定的范围内. 
match : CRegularExpressionValidator 的别名, 确保了特性匹配一个正则表达式. 
numerical : CNumberValidator 的别名, 确保了特性是一个有效的数字. 
required : CRequiredValidator 的别名, 确保了特性不为空. 
type : CTypeValidator 的别名, 确保了特性为指定的数据类型. 
unique : CUniqueValidator 的别名, 确保了特性在数据表字段中是唯一的. 
url : CUrlValidator 的别名, 确保了特性是一个有效的路径.

基本上还是比较全面的,一般的都够用了,但是还是有时候有的验证需要自定义。就以上面的代码为例,我们在添加TAG时需要检查系统之前是否已经存在这个TAG,如果存在则不让用户添加。这个就需要在添加之前去查询数据库,看该TAG是否已经存在,这里我们就需要自定一个验证规则了。

关键有一下两个步骤:

1、在rules中 添加代码:array('tagname', 'checktagname', 'on'=>'create,update'),//插入TAG时检查是否已经存在该tag

注:我在其中用了 'on'=>'create,update',所以这个验证规则之对create,update场景生效

2、在该模型(models)中添加验证函数:

public function checktagname($attribute,$params){ 
  $oldtag = Tag::model()->findByAttributes(array('tagname'=>$this->tagname)); 
  if($oldtag->tagid > 0){ 
    $this->addError($attribute, '该TAG已经存在!'); 
  } 
}

其中需要说明的是:

(1)该验证函数的参数必须是($attribute,$params),不能缺少其中任何一个;

(2)$this->addError($attribute, '该TAG已经存在!');这个是你想要在视图中输出的错误提示信息。

就是这么简单,有了这个方法,表单验证的各种想要的规则就都可以自定义了。

下面给大家介绍Yii自定义验证规则

最简单的定义验证规则的方法是在使用它的模型(model)内部定义。

比方说,你要检查用户的密码是否足够安全.

通常情况下你会使用 CRegularExpression 方法验证,但为了本指南,我们假设不存在此验证方法.

首先在模型(model)中添加两个常量

const WEAK = 0;
const STRONG = 1;然后在模型(model)的 rules 方法中设置:

/**
 * @return array validation rules for model attributes.
 */
public function rules()
{
  return array(
    array('password', 'passwordStrength', 'strength'=>self::STRONG),
  );
}

确保你写的规则不是一个已经存在的规则,否则将会报错.

现在要做的是在模型(model)中创建一个名称为上面填写的规则的方法(即 passwordStrength)。

/**
 * check if the user password is strong enough
 * check the password against the pattern requested
 * by the strength parameter
 * This is the 'passwordStrength' validator as declared in rules().
 */
public function passwordStrength($attribute,$params)
{
  if ($params['strength'] === self::WEAK)
    $pattern = '/^(?=.*[a-zA-Z0-9]).{5,}$/'; 
  elseif ($params['strength'] === self::STRONG)
    $pattern = '/^(?=.*\d(?=.*\d))(?=.*[a-zA-Z](?=.*[a-zA-Z])).{5,}$/'; 
    
  if(!preg_match($pattern, $this->$attribute))
   $this->addError($attribute, 'your password is not strong enough!');
}

刚才创建的方法需要两个参数:* $attribute 需要验证的属性* $params 在规则中自定义的参数

在模型的 rules 方法中我们验证的是 password 属性,所以在验证规则中需要验证的属性值应该是 password.

在 rules 方法中我们还设置了自定义的参数 strength,它的值将会放到 $params 数组中.

你会发现在方法中我们使用了 CModel::addError().

添加错误接受两个参数:第一个参数是在表单中显示错误的属性名,第二个参数时显示的错误信息 。

完整的方法:继承 CValidator 类

如果你想把规则使用在多个模型(model)中,最好的方法时继承 CValidator 类。

继承这个类你可以使用像 CActiveForm::$enableClientValidation (Yii 1.1.7 版本后可用) 类似的其他功能。

创建类文件

首先要做的是创建类文件.最好的方法时类的文件名和类名相同,可以使用 yii 的延迟加载(lazy loading)功能。

让我们在应用(application)的扩展(extensiions)目录(在 protected 文件夹下)下新建一个文件夹.

将目录命名为: MyValidators

然后创建文件: passwordStrength.php

在文件中创建我们的验证方法

class passwordStrength extends CValidator
{
  public $strength;
  private $weak_pattern = '/^(?=.*[a-zA-Z0-9]).{5,}$/';
  private $strong_pattern = '/^(?=.*\d(?=.*\d))(?=.*[a-zA-Z](?=.*[a-zA-Z])).{5,}$/';
...
}

在类中创建属性,此属性为在验证规则中使用的参数.

CValidator 会自动根据参数来填充这些属性.

我们也创建了两个其他的属性,它们为 preg_match 函数使用的正则表达式.

现在我们应该重写父类的抽象方法(abstract method) validateAttribute

/**
 * Validates the attribute of the object.
 * If there is any error, the error message is added to the object.
 * @param CModel $object the object being validated
 * @param string $attribute the attribute being validated
 */
protected function validateAttribute($object,$attribute)
{
  // check the strength parameter used in the validation rule of our model
  if ($this->strength == 'weak')
   $pattern = $this->weak_pattern;
  elseif ($this->strength == 'strong')
   $pattern = $this->strong_pattern;
  // extract the attribute value from it's model object
  $value=$object->$attribute;
  if(!preg_match($pattern, $value))
  {
    $this->addError($object,$attribute,'your password is too weak!');
  }
}

上面的方法我认为就不用解释了.当然你也可以在 if 的条件中使用常量,我推荐使用.

PHP 相关文章推荐
二十行语句实现从Excel到mysql的转化
Oct 09 PHP
用PHP+MySql编写聊天室
Oct 09 PHP
PHP数据库调用类调用实例(详细注释)
Jul 12 PHP
怎么在Windows系统中搭建php环境
Aug 31 PHP
php不写闭合标签的好处
Mar 04 PHP
递归实现php数组转xml的代码分享
May 14 PHP
php实现随机显示图片方法汇总
May 21 PHP
详解php设置session(过期、失效、有效期)
Nov 12 PHP
php简单计算年龄的方法(周岁与虚岁)
Dec 06 PHP
thinkphp3.2同时连接两个数据库的简单方法
Aug 13 PHP
浅谈laravel aliases别名的原理
Oct 24 PHP
Laravel等框架模型关联的可用性浅析
Dec 15 PHP
PHP Yii框架之表单验证规则大全
Nov 16 #PHP
Yii2.0高级框架数据库增删改查的一些操作
Nov 16 #PHP
yii添删改查实例
Nov 16 #PHP
PHP的运行机制与原理(底层)
Nov 16 #PHP
PHP中empty和isset对于参数结构的判断及empty()和isset()的区别
Nov 15 #PHP
php经典算法集锦
Nov 14 #PHP
PHP常用的小程序代码段
Nov 14 #PHP
You might like
怎么使 Mysql 数据同步
2006/10/09 PHP
php构造函数的继承方法
2015/02/09 PHP
PHP目录操作实例总结
2016/09/27 PHP
Swoole实现异步投递task任务案例详解
2019/04/02 PHP
Thinkphp5.0框架使用模型Model的获取器、修改器、软删除数据操作示例
2019/10/11 PHP
Yii 框架入口脚本示例分析
2020/05/19 PHP
niceTitle 基于jquery的超链接提示插件
2010/05/31 Javascript
jQuery的DOM操作之删除节点示例
2014/01/03 Javascript
javascript框架设计读书笔记之种子模块
2014/12/02 Javascript
jQuery插件实现多级联动菜单效果
2015/12/01 Javascript
AngularJS表单和输入验证实例
2016/11/02 Javascript
jQuery扇形定时器插件pietimer使用方法详解
2017/07/18 jQuery
基于JavaScript实现五子棋游戏
2020/08/26 Javascript
关于laydate.js加载laydate.css路径错误问题解决
2017/12/27 Javascript
babel7.x和webpack4.x配置vue项目的方法步骤
2019/05/12 Javascript
VUE+elementui面包屑实现动态路由详解
2019/11/04 Javascript
JavaScript随机数的组合问题案例分析
2020/05/16 Javascript
在Python中使用pngquant压缩png图片的教程
2015/04/09 Python
Python使用numpy实现BP神经网络
2018/03/10 Python
如何基于Python批量下载音乐
2019/11/11 Python
Python之Class&amp;Object用法详解
2019/12/25 Python
pandas-resample按时间聚合实例
2019/12/27 Python
Python面向对象程序设计之类和对象、实例变量、类变量用法分析
2020/03/23 Python
使用 Python 读取电子表格中的数据实例详解
2020/04/17 Python
Python 实现PS滤镜中的径向模糊特效
2020/12/03 Python
实例讲解HTML5的meta标签的一些应用
2015/12/08 HTML / CSS
英国精品买手店:Browns Fashion
2016/09/29 全球购物
STAUD官方网站:洛杉矶独有的闲适风格
2019/04/11 全球购物
网络通讯中,端口有什么含义,端口的取值范围
2012/11/23 面试题
《小猪家的桃花树》教学反思
2014/04/11 职场文书
2014年学校办公室工作总结
2014/12/19 职场文书
行政助理岗位职责范本
2015/04/11 职场文书
业务员年终工作总结2015
2015/05/28 职场文书
有关水浒传的读书笔记
2015/06/25 职场文书
JS数组方法some、every和find的使用详情
2021/10/05 Javascript
python 判断字符串当中是否包含字符(str.contain)
2022/06/01 Python