thinkphp自动验证分析
thinkphp有一个自动验证的方法
验证规则如下
array(
array(验证字段1,验证规则,错误提示,[验证条件,附加规则,验证时间]),
array(验证字段2,验证规则,错误提示,[验证条件,附加规则,验证时间]),
......
);
注:研究源码后发现其实还有第7个参数,是给函数或者回调方法传参数用的,参数1默认为该字段值,如:
array('mobile','is_phone','手机格式不正确',1,'function','参数2,参数3')
验证支付动态和静态
静态验证
在模型类里面预先定义好该模型的自动验证规则,在使用create方法后会自动去验证。
以下是官方的例子
1.首先在模型中定义好验证的规则
namespace Home\Model;
use Think\Model;
class UserModel extends Model{
protected $_validate = array(
array('verify','require','验证码必须!'), // 都有时间都验证
array('name','checkName','帐号错误!',1,'function',4), // 只在登录时候验证
array('password','checkPwd','密码错误!',1,'function',4), // 只在登录时候验证
);
}
2.在调用的时候用create方法会自动进行验证
$User = D("User"); // 实例化User对象
if (!$User->create($_POST,4)){ // 登录验证数据
     // 验证没有通过 输出错误提示信息
     exit($User->getError());
}else{
     // 验证通过 执行登录操作
}
动态验证
以下是官方的例子
$rules = array(
array('verify','require','验证码必须!'), //默认情况下用正则进行验证
array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一
array('value',array(1,2,3),'值的范围不正确!',2,'in'), // 当值不为空的时候判断是否在一个范围内
array('repassword','password','确认密码不正确',0,'confirm'), // 验证确认密码是否和密码一致
array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式
);
$User = M("User"); // 实例化User对象
if (!$User->validate($rules)->create()){
// 如果创建失败 表示验证没有通过 输出错误提示信息
exit($User->getError());
}else{
// 验证通过 可以进行其他数据操作
}
下面是核心的代码分析:
create方法调用后会调用autoValidation方法,方法如下
protected function autoValidation($data,$type) {
    if(!empty($this->options['validate'])) {
        $_validate   =   $this->options['validate'];
        unset($this->options['validate']);
    }elseif(!empty($this->_validate)){
        $_validate   =   $this->_validate;
    }
    // 属性验证
    if(isset($_validate)) { // 如果设置了数据自动验证则进行数据验证
        if($this->patchValidate) { // 重置验证错误信息
            $this->error = array();
        }
        foreach($_validate as $key=>$val) {
            // 验证因子定义格式
            // array(field,rule,message,condition,type,when,params)
            // 判断是否需要执行验证
            //cqh:$val[5]为验证时间,这里判断是设置了验证时间,默认为插入和更新都验证
            if(empty($val[5]) || $val[5]== self::MODEL_BOTH || $val[5]== $type ) {
                if(0==strpos($val[2],'{%') && strpos($val[2],'}'))
                    // 支持提示信息的多语言 使用 {%语言定义} 方式
                    $val[2]  =  L(substr($val[2],2,-1));
                $val[3]  =  isset($val[3])?$val[3]:self::EXISTS_VALIDATE;//$val[3]为验证条件
                $val[4]  =  isset($val[4])?$val[4]:'regex';//$val[4]为验证规则,默认为正则regex
                // 判断验证条件(self::EXISTS_VALIDATE|0:存在字段就验证,self::MUST_VALIDATE|1:必须验证,self::VALUE_VALIDATE|2:值不为空的时候验证
                switch($val[3]) {
                    case self::MUST_VALIDATE:   // 值为1:必须验证 不管表单是否有设置该字段
                        if(false === $this->_validationField($data,$val))
                            return false;
                        break;
                    case self::VALUE_VALIDATE:    // 值为2:值不为空的时候才验证
                        if('' != trim($data[$val[0]]))
                            if(false === $this->_validationField($data,$val))
                                return false;
                        break;
                    default:    // ,默认表单存在该字段就验证
                        if(isset($data[$val[0]]))
                            if(false === $this->_validationField($data,$val))
                                return false;
                }
            }
        }
        // 批量验证的时候最后返回错误
        if(!empty($this->error)) return false;
    }
    return true;
}
以下是$this->_validationField方法,验证表单字段,并收集错误信息到$this->error属性上
/**
* 验证表单字段 支持批量验证
* 如果批量验证返回错误的数组信息
* @access protected
* @param array $data 创建数据
* @param array $val 验证因子
* @return boolean
*/
protected function _validationField($data,$val) {
if($this->patchValidate && isset($this->error[$val[0]]))
return ; //当前字段已经有规则验证没有通过
if(false === $this->_validationFieldItem($data,$val)){
if($this->patchValidate) {
$this->error[$val[0]] = $val[2];
}else{
$this->error = $val[2];
return false;
}
}
return ;
}
以下是$this-> _validationFieldItem方法,返回验证结果
/**
* 根据验证因子验证字段
* @access protected
* @param array $data 创建数据
* @param array $val 验证因子,注意:$val[6]为验证参数
* @return boolean
*/
protected function _validationFieldItem($data,$val) {
switch(strtolower(trim($val[4]))) {
case 'function':// 使用函数进行验证
case 'callback':// 调用方法进行验证
$args = isset($val[6])?(array)$val[6]:array();
if(is_string($val[0]) && strpos($val[0], ','))
$val[0] = explode(',', $val[0]);
if(is_array($val[0])){
// 支持多个字段验证
foreach($val[0] as $field)
$_data[$field] = $data[$field];
array_unshift($args, $_data);
}else{
array_unshift($args, $data[$val[0]]);
}
if('function'==$val[4]) {
return call_user_func_array($val[1], $args);
}else{
return call_user_func_array(array(&$this, $val[1]), $args);
}
case 'confirm': // 验证两个字段是否相同
return $data[$val[0]] == $data[$val[1]];
case 'unique': // 验证某个值是否唯一
if(is_string($val[0]) && strpos($val[0],','))
$val[0] = explode(',',$val[0]);
$map = array();
if(is_array($val[0])) {
// 支持多个字段验证
foreach ($val[0] as $field)
$map[$field] = $data[$field];
}else{
$map[$val[0]] = $data[$val[0]];
}
if(!empty($data[$this->getPk()])) { // 完善编辑的时候验证唯一
$map[$this->getPk()] = array('neq',$data[$this->getPk()]);
}
if($this->where($map)->find()) return false;
return true;
default: // 检查附加规则
return $this->check($data[$val[0]],$val[1],$val[4]);
}
}
以下是附加规则的方法$this->check,验证thinkphp定义好的规则
/**
* 验证数据 支持 in between equal length regex expire ip_allow ip_deny
* @access public
* @param string $value 验证数据
* @param mixed $rule 验证表达式
* @param string $type 验证方式 默认为正则验证
* @return boolean
*/
public function check($value,$rule,$type='regex'){
$type = strtolower(trim($type));
switch($type) {
case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组
case 'notin':
$range = is_array($rule)? $rule : explode(',',$rule);
return $type == 'in' ? in_array($value ,$range) : !in_array($value ,$range);
case 'between': // 验证是否在某个范围
case 'notbetween': // 验证是否不在某个范围
if (is_array($rule)){
$min = $rule[0];
$max = $rule[1];
}else{
list($min,$max) = explode(',',$rule);
}
return $type == 'between' ? $value>=$min && $value<=$max : $value<$min || $value>$max;
case 'equal': // 验证是否等于某个值
case 'notequal': // 验证是否等于某个值
return $type == 'equal' ? $value == $rule : $value != $rule;
case 'length': // 验证长度
$length = mb_strlen($value,'utf-8'); // 当前数据长度
if(strpos($rule,',')) { // 长度区间
list($min,$max) = explode(',',$rule);
return $length >= $min && $length <= $max;
}else{// 指定长度
return $length == $rule;
}
case 'expire':
list($start,$end) = explode(',',$rule);
if(!is_numeric($start)) $start = strtotime($start);
if(!is_numeric($end)) $end = strtotime($end);
return NOW_TIME >= $start && NOW_TIME <= $end;
case 'ip_allow': // IP 操作许可验证
return in_array(get_client_ip(),explode(',',$rule));
case 'ip_deny': // IP 操作禁止验证
return !in_array(get_client_ip(),explode(',',$rule));
case 'regex':
default: // 默认使用正则验证 可以使用验证类中定义的验证名称
// 检查附加规则
return $this->regex($value,$rule);
}
}
以下是正则验证的方法$this->regex,返回正则验证的结果
/**
* 使用正则验证数据
* @access public
* @param string $value 要验证的数据
* @param string $rule 验证规则
* @return boolean
*/
public function regex($value,$rule) {
$validate = array(
'require' => '/\S+/',
'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/',
'currency' => '/^\d+(\.\d+)?$/',
'number' => '/^\d+$/',
'zip' => '/^\d{6}$/',
'integer' => '/^[-\+]?\d+$/',
'double' => '/^[-\+]?\d+(\.\d+)?$/',
'english' => '/^[A-Za-z]+$/',
);
// 检查是否有内置的正则表达式
if(isset($validate[strtolower($rule)]))
$rule = $validate[strtolower($rule)];
return preg_match($rule,$value)===1;
}
thinkphp自动验证分析的更多相关文章
- ThinkPHP 自动验证与自动填充无效可能的原因(转)
		自动验证与自动填充是在使用ThinkPHP时经常用到的功能,但偶尔会遇到自动验证与自动填充无效的情况,本文就ThinkPHP 自动验证与自动填充无效可能的原因做一些分析. create() Think ... 
- ThinkPHP 自动验证与自动填充无效可能的原因
		原文链接:http://www.5idev.com/p-thinkphp_validate_auto_Invalid.shtml 自动验证与自动填充是在使用ThinkPHP时经常用到的功能,但偶尔会遇 ... 
- <转>thinkphp自动验证无效的问题
		新手入门thinkphp,试用自动验证表单输入数据功能,却发现怎么都不能调用自动验证,自动验证无效,原因竟是一个小细节的疏忽,学习一定要细心啊! Action方法: IndexAction下的adds ... 
- ThinkPHP 自动验证实例
		//array(验证字段1,验证规则,错误提示,[验证条件,附加规则,验证时间]),protected $_validate = array( ); ThinkPHP 自动验证定义的附加规则如下: r ... 
- thinkphp自动验证无效的问题
		新手入门thinkphp,试用自动验证表单输入数据功能,却发现怎么都不能调用自动验证,自动验证无效,原因竟是一个小细节的疏忽,学习一定要细心啊! Action方法: IndexAction下的adds ... 
- thinkphp自动填充分析
		thinkphp有一个自动填充字段的方法填充规则如下 array( array(完成字段1,完成规则,[完成条件,附加规则]), array(完成字段2,完成规则,[完成条件,附加规则]), .... ... 
- thinkphp自动验证---$_validate
		thinkphp中的自动验证 array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间]) 1.验证字段 需要验证的表单字段名称,这个字段不一定是数据库字段,也可以是表单的一些辅助字段 ... 
- ThinkPHP自动验证
		自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证. 验证规则 数据验证可以进行数据类型.业务规则.安全判断等方面的验证操作.数据验证有两 ... 
- thinkphp自动验证详解
		自动验证时THINKPHP提供的一种比较好的验证方式,可以在使用create创建数据对象的时候自动进行数据验证. 数据进行自动验证的方式有两种: 1.静态方式:在模型类里面通过$_validate属性 ... 
随机推荐
- idea取消vim模式
			在安装idea时选择了vim编辑模式,但是用习惯了eclipse,总是要拷贝粘贴,在idea中一直按ctrl+c和ctrl+v不起总用.于是想把vim模式关闭掉.方法:菜单栏:tools->vi ... 
- ehcache缓存使用
			CacheUtils.java //工具类 保存cache缓存: CacheUtils.put(CacheUtils.SIGN_CACHE, childid + "_" + mNu ... 
- 修改云主机windows密码不生效
			Step1:使用文本工具打开插件路径: 路径为:C:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Lib\site-packages ... 
- Windows下 tensorboard出现ValueError:Invalid format string
			Windows下 tensorboard出现ValueError:Invalid format string错误时,是格式错误问题,解决方法参阅我的另一篇博客 https://www.jianshu. ... 
- JavaScript基础视频教程总结(131-140章)
			<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ... 
- cp/tar/用c语言编写程序 实现cp命令的效果
			1.cp (拷贝) 已存在文件路径 要拷贝的文件路径 实现cp命令的代码如下: #include <stdio.h> //因为要在命令中得到两个路径,所以要用到main函数的两个参数 i ... 
- 【慕课网实战】三、以慕课网日志分析为例 进入大数据 Spark SQL 的世界
			前置要求: 1)Building Spark using Maven requires Maven 3.3.9 or newer and Java 7+ 2)export MAVEN_OPTS=&qu ... 
- 写给笨蛋徒弟的学习手册(3)—C#中15个预定义数据类型
			在C#中学习中,你会很早的遇到预定义数据类型这个概念,但你有没有仔细想过它存在的意义?正所谓“存在即合理”,预定义数据类型的存在目的主要有俩个方面,一是为了增加程序的安全性,同时减轻编译器负担,加快编 ... 
- Exp4 恶意代码分析 20154320 李超
			恶意代码 概述 恶意代码是指故意编制或设置的.对网络或系统会产生威胁或潜在威胁的计算机代码.最常见的恶意代码有计算机病毒(简称病毒).特洛伊木马(简称木马).计算机蠕虫(简称蠕虫).后门.逻辑炸弹等. ... 
- Gigabyte Z170N-WIFI 黑苹果 10.12
			简述 (此文在我的个人博客长期更新)[http://aiellochan.com/2018/02/11/play/Gigabyte-Z170N-WIFI-%E9%BB%91%E8%8B%B9%E6%9 ... 
