个人需求,仿着CI的表单验证写了一个自己的验证类
1.定义验证类
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); // required No 如果元素为空,则返回FALSE // matches Yes 如果表单元素的值与参数中对应的表单字段的值不相等,则返回FALSE matches[form_item] // is_unique Yes 如果表单元素的值与指定数据表栏位有重复,则返回False(译者注:比如is_unique[User.Email],那么验证类会去查找User表中Email栏位有没有与表单元素一样的值,如存重复,则返回false,这样开发者就不必另写Callback验证代码。) is_unique[table.field] // min_length Yes 如果表单元素值的字符长度少于参数中定义的数字,则返回FALSE min_length[6] // max_length Yes 如果表单元素值的字符长度大于参数中定义的数字,则返回FALSE max_length[12] // exact_length Yes 如果表单元素值的字符长度与参数中定义的数字不符,则返回FALSE exact_length[8] // greater_than Yes 如果表单元素值是非数字类型,或小于参数定义的值,则返回FALSE greater_than[8] // less_than Yes 如果表单元素值是非数字类型,或大于参数定义的值,则返回FALSE less_than[8] // alpha No 如果表单元素值中包含除字母以外的其他字符,则返回FALSE // alpha_numeric No 如果表单元素值中包含除字母和数字以外的其他字符,则返回FALSE // alpha_dash No 如果表单元素值中包含除字母/数字/下划线/破折号以外的其他字符,则返回FALSE // numeric No 如果表单元素值中包含除数字以外的字符,则返回 FALSE // integer No 如果表单元素中包含除整数以外的字符,则返回FALSE // decimal No 如果表单元素中包含非十进制数字时,则返回FALSE // is_natural No 如果表单元素值中包含了非自然数的其他数值 (其他数值不包括零),则返回FALSE。自然数形如:0,1,2,3....等等。 // is_natural_no_zero No 如果表单元素值包含了非自然数的其他数值 (其他数值包括零),则返回FALSE。非零的自然数:1,2,3.....等等。 // valid_email No 如果表单元素值包含不合法的email地址,则返回FALSE // valid_emails No 如果表单元素值中任何一个值包含不合法的email地址(地址之间用英文逗号分割),则返回FALSE。 // valid_ip No 如果表单元素的值不是一个合法的IP地址,则返回FALSE。通过可选参数"IPv4"或"IPv6"来指定 IP 地址格式。 // valid_base64 No 如果表单元素的值包含除了base64 编码字符之外的其他字符,则返回FALSE。 class Validation { protected $_field_data = array(); protected $_config_rules = array(); public function __construct() { //获取CI对象 $this->CI =& get_instance(); //读取验证类配置文件 TODO } public function set_rules($field, $rules = '') { //如果field是数组,我们遍历它并递归调用这些验证方法 if (is_array($field)) { foreach ($field as $key => $row) { //检查数组数据 if (!isset($row['field']) OR !isset($row['rules'])){ continue; } $this->set_rules($row['field'], $row['rules']); } return $this; } //不存在$field或者为空,返回 if (!is_string($field) OR $field == '') { return $this; } //如果field是数组,拆分 if (strpos($field, '[') !== FALSE AND preg_match_all('/\[(.*?)\]/', $field, $matches)) { foreach ($matches[1] as $index) { if ($index != ''){ $indexes[] = $index; } } $is_array = TRUE; } else { $indexes = array(); $is_array = FALSE; } //设置字段规则 $this->_field_data[$field] = array( 'field' => $field, 'rules' => $rules, 'is_array' => $is_array, 'keys' => $indexes, 'data' => NULL, ); return $this; } public function _reduce_array($array, $keys, $i = 0) { if(is_array($array)) { //递归查询每个键名下的数组 if (isset($keys[$i])){ if (isset($array[$key[$i]])) { $array = $this->_reduce_array($array[$key[$i]], $keys, ($i+1)); } else{ return NULL; } } else { return $array; } } return $array; } public function _execute($row, $cycles = 0) { $is_valid = TRUE; //如果字段数据data是数组,我们执行递归调用 if (is_array($row['data'])) { foreach ($data as $key => $value) { if ( ! $this->_execute($row, $cycles)) { $is_valid = FALSE; break; } $cycles++; } return $is_valid; } extract($row); // -------------------------------------------------------------------- //如果字段为空,并不要求,没必要进行验证 $callback = FALSE; if (!in_array('required', $rules) AND is_null($data)){ return $is_valid; } // -------------------------------------------------------------------- //应用到复选框TODO // -------------------------------------------------------------------- //遍历并执行验证 foreach ($rules as $key => $rule) { //如果验证规则带有回调函数 $callback = FALSE; if (substr($rule, 0, 9) == 'callback_'){ $rule = substr($rule, 9); $callback = TRUE; } //如果验证规则带有参数 $param = FALSE; if (preg_match("/(.*?)\[(.*)\]/", $rule, $match)){ $rule = $match[1]; $param= $match[2]; } // 调用对应规则的方法验证 // 回调函数验证 if ($callback === TRUE) { if (!method_exists($this->CI, $rule)){ continue; } $is_valid = $this->CI->$rule($data, $param); //如果不要求并验证结果为真,不进行其他规则的验证 if ( ! in_array('required', $rules, TRUE) AND $is_valid !== FALSE) { continue; } } else{ //如果验证类中不包含该验证方法,尝试php内置方法 if (!method_exists($this, $rule)) { if (function_exists($rule)) { $is_valid = $rule($data); } else { log_message('error', "找不到对应的验证方法:".$rule); } continue; } $is_valid = $this->$rule($data, $param); } //如果验证不通过,记录错误 if ($is_valid === FALSE) { if (isset($this->_error_messages[$rule])) { log_message('error', $field.$cycles.'验证'.$rule.'不通过'); } return $is_valid; } } return TRUE; } public function run($data) { //如果没有设置验证规则 if (count($this->_field_data) == 0) { //检查是否设置默认验证规则配置文件 //TODO } foreach ($this->_field_data as $field => $row) { //根据field的名字是数组或者字符串,决定我们从哪里获取它的值 if ($row['is_array'] == TRUE) { $row['data'] = $this->_reduce_array($data, $row['keys']);//获取多维数组的值 } else { if (isset($data[$field]) AND $data[$field] != ''){ $row['data'] = $data[$field]; } } //执行验证 if (!$this->_execute($row)){ return FALSE; } } return TRUE; } public function required($str) { log_message('error',$str); if (!is_array($str)) { return (trim($str) == '') ? FALSE : TRUE; } else { return (!empty($str)); } } /** * Performs a Regular Expression match test. * * @access public * @param string * @param regex * @return bool */ public function regex_match($str, $regex) { if ( ! preg_match($regex, $str)) { return FALSE; } return TRUE; } // -------------------------------------------------------------------- /** * Match one field to another * * @access public * @param string * @param field * @return bool */ public function is_unique($str, $field) { list($table, $field)=explode('.', $field); $query = $this->CI->db->limit(1)->get_where($table, array($field => $str)); return $query->num_rows() === 0; } // -------------------------------------------------------------------- /** * Minimum Length * * @access public * @param string * @param value * @return bool */ public function min_length($str, $val) { if (preg_match("/[^0-9]/", $val)) { return FALSE; } if (function_exists('mb_strlen')) { return (mb_strlen($str) < $val) ? FALSE : TRUE; } return (strlen($str) < $val) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Max Length * * @access public * @param string * @param value * @return bool */ public function max_length($str, $val) { if (preg_match("/[^0-9]/", $val)) { return FALSE; } if (function_exists('mb_strlen')) { return (mb_strlen($str) > $val) ? FALSE : TRUE; } return (strlen($str) > $val) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Exact Length * * @access public * @param string * @param value * @return bool */ public function exact_length($str, $val) { if (preg_match("/[^0-9]/", $val)) { return FALSE; } if (function_exists('mb_strlen')) { return (mb_strlen($str) != $val) ? FALSE : TRUE; } return (strlen($str) != $val) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Valid Email * * @access public * @param string * @return bool */ public function valid_email($str) { return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Valid Emails * * @access public * @param string * @return bool */ public function valid_emails($str) { if (strpos($str, ',') === FALSE) { return $this->valid_email(trim($str)); } foreach (explode(',', $str) as $email) { if (trim($email) != '' && $this->valid_email(trim($email)) === FALSE) { return FALSE; } } return TRUE; } // -------------------------------------------------------------------- /** * Validate IP Address * * @access public * @param string * @param string "ipv4" or "ipv6" to validate a specific ip format * @return string */ public function valid_ip($ip, $which = '') { return $this->CI->input->valid_ip($ip, $which); } // -------------------------------------------------------------------- /** * Alpha * * @access public * @param string * @return bool */ public function alpha($str) { return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Alpha-numeric * * @access public * @param string * @return bool */ public function alpha_numeric($str) { return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Alpha-numeric with underscores and dashes * * @access public * @param string * @return bool */ public function alpha_dash($str) { return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Numeric * * @access public * @param string * @return bool */ public function numeric($str) { return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str); } // -------------------------------------------------------------------- /** * Is Numeric * * @access public * @param string * @return bool */ public function is_numeric($str) { return ( ! is_numeric($str)) ? FALSE : TRUE; } // -------------------------------------------------------------------- /** * Integer * * @access public * @param string * @return bool */ public function integer($str) { return (bool) preg_match('/^[\-+]?[0-9]+$/', $str); } // -------------------------------------------------------------------- /** * Decimal number * * @access public * @param string * @return bool */ public function decimal($str) { return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str); } // -------------------------------------------------------------------- /** * Greather than * * @access public * @param string * @return bool */ public function greater_than($str, $min) { if ( ! is_numeric($str)) { return FALSE; } return $str > $min; } // -------------------------------------------------------------------- /** * Less than * * @access public * @param string * @return bool */ public function less_than($str, $max) { if ( ! is_numeric($str)) { return FALSE; } return $str < $max; } // -------------------------------------------------------------------- /** * Is a Natural number (0,1,2,3, etc.) * * @access public * @param string * @return bool */ public function is_natural($str) { return (bool) preg_match( '/^[0-9]+$/', $str); } // -------------------------------------------------------------------- /** * Is a Natural number, but not a zero (1,2,3, etc.) * * @access public * @param string * @return bool */ public function is_natural_no_zero($str) { if ( ! preg_match( '/^[0-9]+$/', $str)) { return FALSE; } if ($str == 0) { return FALSE; } return TRUE; } // -------------------------------------------------------------------- /** * Valid Base64 * * Tests a string for characters outside of the Base64 alphabet * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045 * * @access public * @param string * @return bool */ public function valid_base64($str) { return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str); } }
因为我只支持前台能运行js的用户,只是防止非法人跨过浏览器直接访问
所以,我的验证类阉割了原来显示验证错误的功能,一旦有一个验证不通过,记录日志并直接退出!简单粗暴 哈哈
另外,该类还有没有完善的地方,复选框部分代码,和读取配置文件设置默认验证规则的代码,回调函数只能限制在控制器的问题,待完善
2.加入自动加载中
3.配置使用 在控制器中加入如下代码,
//验证$input $rules = array( array('field' => 'name','rules' => array('required', 'callback_test')) ); if (!$this->validation->set_rules($rules)->run($input)){ exit('请检查是否javascript不生效了!'); }