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属性 ...
随机推荐
- C# MVC验证Model
.NET Core MVC3 数据模型验证的使用 这里我先粘贴一个已经加了数据验证的实体类PeopleModel,然后一一介绍. using System; using System.Collecti ...
- JDBC&Oracle启动
[Wed Apr 26 2017 16:05:11 GMT+0800]PLSQL Developer连接远程oracle配置(本地不安装客户端).在windows机器上不想安装oracle或者orac ...
- RISC精简指令集系统计算机
特点: 选用使用频率高的简单指令,复杂指令由简单指令组合完成 固定指令长度 只有Load/Store指令访存,其他指令都在寄存器中进行 CPU中寄存器数量多 一定采用指令流水,大部分指令在一个时钟周期 ...
- post和get请求的参数乱码
对于做Java WEB项目同学来说,中文乱码问题是一个经常遇到而又非常头痛的问题,而最容易出现乱码的环节就是在浏览器向服务器发送请求的过程,至于出现乱码的原因不是本文的关注的重点,想了解的朋友可以参考 ...
- kvm-qcow2派生镜像的远程备份的方法!
在虚拟化环境中,关于虚拟机的远程备份是一个比较重要的环节,这个是有关于整个机房挂掉之后,仍然可以恢复的最后一招. 在kvm中这种情况可以通过直接备份虚拟机的镜像文件(qcow2)到远端存储解决. 但有 ...
- input type='file'文件上传自定义样式
使用场景: 在未使用UI库时免不了会用到各种上传文件,那么默认的上传文件样式无法达到项目的要求,因此重写(修改)上传文件样式是必然的,下面的效果是最近项目中自己写的一个效果,写出来做个记录方便以后使用 ...
- 基于MFC的socket编程
网络编程 1.windows 套接字编程(开放的网络编程接口)添加头文件#include<windows.h> 2.套接字及其分类 socket分为两种:(1)数据报socket:无连接套 ...
- Docker基础知识介绍
本节内容 1. Docker概述 2. Docker的安装 3. Docker基本使用 4. Docker相关命令汇总 5. Docker概念理解 一 Docker概述 Docker是什么 ...
- 【Node100In1】01.去异步,解决掉Node.js万恶的回调陷阱
Node.js是基于事件驱动编程.异步函数随处可见,其中不乏一些常用库的方法.本例就以js中最常见的setTimeout的为例,试图改善一下回调的书写. 先来看一段伪代码: 我们实现一个需求,每隔一段 ...
- 逆水行舟 —— MyBatis
第一轮总结性笔记 这是一个很漫长的过程,我买了套课程,将在日后记录学习笔记,取名为逆水行舟系列 MyBatis的基础 根据MyBatis的官方介绍: 整个测试项目结构如下:使用Maven架构项目 po ...