数据验证
  1. 什么是数据验证

    我们平时处理数据,一般包含以下三步:
    1.检验数据合法性
    2.获取检验过的合法数据
    3.根据业务逻辑保存数据
  2. 数据验证

    在我们的代码里可以通过下面的方法进行数据验证。
    						Sr::checkData($data, $rules, &$returnData, &$errorMessage, &$errorKey = null, &$db = null) 
    					
    参数说明:
    $data 需要检验的数据,一般是表单Sr::post()数据,或者其它数组数据都可以。
    格式:
    						array('key1'=>'值1',...,'keyn'=>'值n',)
    					
    $rules 验证规则
    格式:
    					array(
    						'key1'=>array(
    							'规则1'=>'验证失败提示信息',
    							.....
    							'规则n'=>'验证失败提示信息'
    						),
    						....
    						'keyn'=>array(
    							'规则1'=>'验证失败提示信息',
    							.....
    							'规则n'=>'验证失败提示信息'
    						),
    					)
    					
    $returnData 验证通过后,处理过的数据,
    这个应该是我们下一步要使用的合法数据,比如读取其中的数据插入数据库等。
    $errorMessage 当验证失败的时候这个变量存储的就是错误提示信息。
    $errorKey 当验证失败的时候这个变量存储的就是验证失败的那个key字段名称。
    $db 当unique和exists规则验证的数据不是当前默认的数据库连接时,可以指定使用的数据库连接对象。
    示例:
    继续上面2中的数据,为了安全,我们需要检验$data=array('title'=>'值','content'=>'值')
    首先我们总结下要验证的逻辑:
    1.标题不能为空,过滤html,剔除两边空格,长度最大50字符。
    2.内容不能为空,要进行xss过滤。
    那么我们的验证规则就是:
    						$rule=array(
    							'atitle'=>array(
    								'functions[strip_tags,trim]'=>'',
    								'required'=>'标题不能为空',
    								'max_len[50]'=>'标题最多50字符'
    							),
    							'content'=>array(
    								'required'=>'内容不能为空',
    								'xss'=>'',
    							)
    						);
    					
    接着我们就可以通过规则验证$data数据了,代码如下:
    						$isOkay=Sr::checkData($data,$rule,$retData,$errorMsg);
    						if($isOkay){
    							//验证成功,$retData是验证处理过的数据。
    							//do sth else
    							Sr::dump($retData);
    						}else{
    							//验证失败,$errorMsg是提示信息
    							echo $errorMsg;
    						}
    					
    上面验证规则用到了很多规则,最下面是Soter支持的所有规则和用法。
  3. 读取数据

    在我们的代码里可以通过下面的方法进行读取数据,根据$map从$sourceData中读取数据。
    						Sr::readData(Array $map, $sourceData = null) 
    					
    参数说明:
    $map 字段映射数组,格式:array('表单name名称'=>'表字段名称',...)
    $sourceData 数据源,格式:array('表单name名称'=>'值',...),一般是$_POST。
    最后会返回读取后的数据,格式是:array('表字段名称'=>'值',...)。
    示例:
    比如表单数据:
    标题:$_POST['title'] = ' 文章xxx标题 ';
    内容:$_POST['content']='内容xxx内容,xxx脚本';
    防止跨站token:$_POST['token'] = '09adfu09adfmca09dma0';
    标题和内容对应数据库字段:art_title,art_content
    $map=array('title'=>'art_title','content'=>'art_content');
    然后我们就可以通过Sr::checkData()验证数据的合法性,最后读取验证后的数据插入数据库。
    						$isOkay=Sr::checkData($_POST,$rule,$retData,$errorMsg);
    						if($isOkay){
    							//验证成功,$retData是验证处理过的数据。
    							//从$retData中读取要插入数据库的数据放入$data
    							$data=Sr::readData($map,$retData);
    						}else{
    							//验证失败,$errorMsg是提示信息
    							echo $errorMsg;
    						}
    					
    上面读到的$data=array('art_title'=>'值','art_content'=>'值'),可以看到把无关的表单字段都过滤掉了。
  4. 自定义验证规则

    Soter提供了一些验证规则,但是这些规则肯定无法满足所有的需求,那么我们可以拓展Soter的验证规则。
    在入口文件里面我们可以看到下面的配置:
    						//设置自定义数据验证规则,参数可以是配置文件名称,也可以是规则数组
    						->setDataCheckRules('rules')
    					
    配置文件rules.php内容如下:
    						//验证规则返回布尔代表成功和失败
    						//如果要改变传入的值,把改变后的值赋值给$returnValue变量即可
    						//对于一个字段多条验证规则存在的时候,如果设置$break为true那么该字段的该条规则之后的验证规则不在起作用
    
    						return array(
    							'myRule' => function($key, $value, $data, $args, &$returnValue, &$break, &$db) {
    								    if ($value<100) {
    									   return false;
    								    }
    								    return true;
    							},
    							'encodePassword' => function($key, $value, $data, $args, &$returnValue, &$break, &$db) {
    									if (!$value) {
    									       return false;
    									}
    									$returnValue=md5($value);
    									return true;
    							    },
    							'optional' => function($key, $value, $data, $args, &$returnValue, &$break, &$db) {
    								    $break=!isset($data[$key]);
    								    return true;
    							},
    						);
    					
    可以看到我们自定义了规则,名称是myRule和encodePassword,规则是一个匿名函数,函数接收了几个参数,
    然后函数里面进行了一些逻辑验证,返回验证成功还是失败。
    而且上面的规则还自定义了一个和系统规则相同的optional,那么系统规则就会被这里的规则覆盖。
    参数含义如下:
    $key 要验证的数据在$data中的key键
    $value 要验证的数据,也就是:$data[$key]
    $data 要验证的数据
    $args 规则后面的参数数组,比如:range_len[6,16],那么$args就是array(6,16)
    $returnValue 如果要改变传入$value的值,把改变后的值赋值给$returnValue变量即可。
    比如上面我们自定义规则encodePassword,把值md5加密了一次,
    那么Sr::checkData($data, $rules, &$returnData, &$errorMessage, &$errorKey, &$db = null)验证数据通过之后,
    $returnData的数据中的使用了encodePassword规则的字段都会被md5加密。
    $break 对于一个字段多条验证规则存在的时候,如果设置$break为true那么该字段的该条规则之后的验证规则不在起作用
    返回值说明:
    返回布尔代表成功和失败。
    返回成功ture,Soter会使用字段的验证规则数组中当前规则下面的规则继续验证。
    返回失败false,Soter会终止验证,设置验证失败信息,然后返回false验证失败。
  5. Soter验证规则

    规则名称 功能描述 举例
    array 如果元素不是数组,则返回FALSE。
    如果元素不满足数组长度范围,则返回FALSE
    array 元素值必须是数组,可以为空。
    array[2],数组长度最小是2
    array[1,2],数组长度必须是1到2
    array[2,2],数组长度必须是2
    notArray 如果元素值是数组,则返回FALSE。
    required 如果元素为空,则返回FALSE。
    支持数组,数组的时候,数组为空或者数组中有一个元素为空则返回FALSE。
    requiredKey 如果数据中不存在指定的键名称,则返回FALSE。 requiredKey 数据中必须包含当前字段。 requiredKey[email] 数据中必须包含当前字段和email字段。
    requiredKey[email,user] 数据中必须包含当前字段和email,user字段。
    default 当没有对应字段的值或者值为空的时候那么就会使用默认规则的值作为该字段的值。然后用这个值继续后面的规则进行验证。
    支持数组,数组的时候,数组中为空的元素会使用默认规则的参数值作为元素的值。
    default[默认值]
    数组的时候可以设置多个默认值:
    default[默认值0,默认值1,默认值2...默认值n]
    默认值依次赋值给数组的元素,如果只设置了“默认值0”那么数组所有的元素值都会被设置为“默认值0”
    optional 可以为空规则。这个规则应该在字段验证规则数组里面第一位。因为验证是按着字段验证规则数组从前往后验证的。
    functions 调用系统函数,这些函数应该都是至少接收一个参数,然后返回处理后的结果,比如trim,htmlspceialchars。
    支持数组,数组的时候,数组里面的所有元素都会使用这些函数处理。
    functions[htmlspecialchars]
    functions[trim,md5]
    xss 过滤xss代码,要验证的数据可以是字符串也可以是数组。
    match 如果表单元素的值与参数中对应的表单字段的值不相等,则返回FALSE match[password2]
    equal 如果表单元素的值不与指定的值相等,则返回FALSE。 equal[snail]
    enum 如果表单元素值不在指定的几个值中,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素不在指定的几个值中,则返回FALSE。
    enum[0,1]
    unique 如果表单元素的值与指定数据表栏位有重复,则返回False(注:比如unique[user.email],那么验证类会去查找user表中email字段有没有与表单元素一样的值,如存重复,则返回false,这样开发者就不必另写callback验证代码。如果指定了id:1,那么除了id为1之外的记录的email字段不能与表单元素一样,如果一样返回false)
    unique[table.field,id:1],其中的id:1支持变量。
    比如:id:#user_id,
    那么就会使用get或者post的user_id内容作为id内容。
    unique[table.field]
    unique[table.field,id:1]
    exists 规则说明:
    (1).如果表单元素的值在指定数据表的字段中不存在则返回false,如果存在返回true
    (2).比如exists[cat.cid],那么验证类会去查找cat表中cid字段有没有与表单元素一样的值
    (3).cat.cid,cat是表名称(不要带前缀)cid是字段名称。
    cat.cid后面还可以指定附加的where条件。
    比如:exists[users.uname,user_id:2,...] 可以多个条件,逗号分割。
    上面的规则生成的where条件就是array('uname'=>$value,'user_id'=>2,....) exists[table.field,id:1],其中的id:1支持变量。
    比如:id:#user_id,
    那么就会使用get或者post的user_id内容作为id内容。
    exists[table.field]
    exists[table.field,id:1]
    exists[table.field,id:#id]
    min_len 如果表单元素值的字符长度小于参数定义的值,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素的字符长度小于参数定义的值,则返回FALSE。
    min_len[8]
    max_len 如果表单元素值的字符长度大于参数定义的值,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素的字符长度大于参数定义的值,则返回FALSE。
    max_len[8]
    range_len 如果表单元素值的字符长度不在指定的范围,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素的字符长度不在指定的范围,则返回FALSE。
    range_len[6,16]
    len 如果表单元素值的字符长度不是指定的大小,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值的字符长度不是指定的大小,则返回FALSE。
    len[8]
    min 如果表单元素值不是数字或者小于指定的值,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素的值不是数字或者小于指定的值,则返回FALSE。
    min[8]
    max 如果表单元素值不是数字或者大于指定的值,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是数字或者大于指定的值,则返回FALSE。
    max[8]
    range 如果表单元素值不是数字或者大小不在指定的范围内,则返回 FALSE。
    支持数组,数组的时候,数组里面存在元素值不是数字或者大小不在指定的范围内,则返回FALSE。
    range[1,10]
    alpha 如果元素值中包含除字母以外的字符,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值中包含除字母以外的字符,则返回FALSE。
    alpha_num 如果表单元素中包含除字母和数字以外的字符,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值中包含除字母和数字以外的字符,则返回FALSE。
    alpha_dash 如果表单元素值中包含除字母/数字/下划线/破折号以外的其他字符,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值中包含除字母/数字/下划线/破折号以外的其他字符,则返回FALSE。
    alpha_start 如果元素值不是字母开头,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是字母开头,则返回FALSE。
    num 如果表单元素中不是纯数字,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是纯数字,则返回FALSE。
    int 如果表单元素中不是整数,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是整数,则返回FALSE。
    float 如果表单元素中不是小数,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是小数,则返回FALSE。
    numeric 如果表单元素中不是一个数,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个数,则返回FALSE。
    natural 如果表单元素值中包含了非自然数的其他数值(其他数值不包括零),则返回FALSE。自然数形如:0,1,2,3....等等。
    支持数组,数组的时候,数组里面存在元素值包含了非自然数的其他数值(其他数值不包括零),则返回FALSE。
    natural_no_zero 如果表单元素值包含了非自然数的其他数值 (其他数值包括零),则返回FALSE。非零的自然数:1,2,3.....等等。
    支持数组,数组的时候,数组里面存在元素值包含了非自然数的其他数值(其他数值包括零),则返回FALSE。
    email 如果表单元素值包含不合法的email地址,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值包含不合法的email地址,则返回FALSE。
    email 必须是email,不能为空
    email[true] 必须是email,可以为空。
    url 如果表单元素值不是一个网址,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个网址,则返回FALSE。
    url 必须是url,不能为空
    url[true] 必须是url,可以为空
    qq 如果表单元素值不是一个QQ号,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个QQ号,则返回FALSE。
    qq 必须是qq,不能为空
    qq[true] 必须是qq,可以为空
    phone 如果表单元素值不是一个电话号码,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个电话号码,则返回FALSE。
    phone 必须是电话号码,不能为空
    phone[true] 必须是电话号码,可以为空
    mobile 如果表单元素值不是一个手机号,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个手机号,则返回FALSE。
    mobile 必须是手机号,不能为空
    mobile[true] 必须是手机号,可以为空
    zipcode 如果表单元素值不是一个邮政编码,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个邮政编码,则返回FALSE。
    zipcode 必须是邮政编码,不能为空
    zipcode[true] 必须是邮政编码,可以为空
    idcard 如果表单元素值不是一个身份证号,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个身份证号,则返回FALSE。
    idcard 必须是身份证号,不能为空
    idcard[true] 必须是身份证号,可以为空
    ip 如果表单元素值不是一个合法的IPv4地址,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是一个合法的IPv4地址,则返回FALSE。
    ip 必须是IPv4地址,不能为空
    ip[true] 必须是IPv4地址,可以为空
    chs 如果表单元素值不是汉字,或者不是指定的长度,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是汉字,或者不是指定的长度,则返回FALSE。
    chs 必须是汉字不能为空
    chs[false] 必须是汉字,不能为空
    chs[true] 必须是汉字,可以为空
    chs[false,2] 必须是2个汉字,不能为空
    chs[true,2] 必须是2个汉字,可以为空
    chs[true,2,3] 必须是2-3个汉字,可以为空
    chs[false,2,] 必须是2个以上汉字,不能为空
    date 如果表单元素值不是正确的日期格式YYYY-MM-DD,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是正确的日期格式YYYY-MM-DD,则返回FALSE。
    date 必须是正确的日期格式,不能为空
    date[true] 必须是正确的日期格式,可以为空
    time 如果表单元素值不是正确的时间格式HH:MM:SS,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是正确的时间格式HH:MM:SS,则返回FALSE。
    time 必须是正确的时间格式,不能为空
    time[true] 必须是正确的时间格式,可以为空
    datetime 如果表单元素值不是正确的日期时间格式YYYY-MM-DD HH:MM:SS,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不是正确的日期时间格式YYYY-MM-DD HH:MM:SS,则返回FALSE。
    datetime 必须是正确的日期时间格式,不能为空
    datetime[true] 必须是正确的日期时间格式,可以为空
    reg 如果表单元素值不匹配指定的正则表达式,则返回FALSE。
    支持数组,数组的时候,数组里面存在元素值不匹配指定的正则表达式,则返回FALSE。
    reg[/^[]]$/]
    reg[/^A$/i]
    模式修正符说明:
    i 表示在和模式进行匹配进不区分大小写
    m 将模式视为多行,使用^和$表示任何一行都可以以正则表达式开始或结束
    s 如果没有使用这个模式修正符号,元字符中的"."默认不能表示换行符号,将字符串视为单行
    x 表示模式中的空白忽略不计
    e 正则表达式必须使用在preg_replace替换字符串的函数中时才可以使用(讲这个函数时再说)
    A 以模式字符串开头,相当于元字符^
    Z 以模式字符串结尾,相当于元字符$
    U 正则表达式的特点:就是比较“贪婪”,使用该模式修正符可以取消贪婪模式
    参数默认分割符 参数默认分割符是逗号, 可以改变这个符号,通过在]后面指定即可。 range[3#5]# 使用#分割参数