美文网首页
表单验证类 PHP

表单验证类 PHP

作者: 晓得为_ | 来源:发表于2017-05-04 11:39 被阅读0次

    验证类

    1.提供两种调用方式
    Validator::ValidatorInput 验证input数组
    Validator::ValidatorInputRow 验证一行
    2.验证规则两种写法
    竖线分隔:ruler = 'type=int|required|min=3'; 数组模式 :ruler = array('type'=>'int','required'=>true,'min'=>10,);

    3.扩展
    自定义 {$type}Validator 方法 扩展验证类

    使用示例

    $arrInput = array(
        'orderId' => '3',
        'status' => '3',
    );
    $arrValidationRule = array(
        'orderId' => 'type=int|required|min=3',// int 必须 最小值 3
        'status' => 'type=int|status|enum=1,2,3,4|cnName=状态',// string  非必需   枚举[1,2,3,4]   中文名= 状态
    );
    Validator::ValidatorInput($arrInput, $arrValidationRule);
    
    ---
    // int 必须 最小值 3
    Validator::ValidatorInputRow($orderId,'type=int|required|min=3','orderId');
    
    // string  非必需   枚举[1,2,3,4]   中文名= 状态
    
    Validator::ValidatorInputRow($status,'type=string|status|enum=1,2,3,4|cnName=状态','status');
    
    

    验证类

    <?php
    
    /**
     * Created by PhpStorm.
     * Date: 2018/1/11  16:54
     */
    class Validator {
        const  ERR_CODE_INPUT_ERROR = 4000001;
        const  ERR_CODE_INPUT_REQUIRED = 4000002;
        const  ERR_CODE_INPUT_TYPE = 4000003;
    
        const  ERR_CODE_CHECK_REFER = 4000100;
    
        public static $MSG = array(
            self::ERR_CODE_INPUT_ERROR    => '参数错误',
            self::ERR_CODE_INPUT_REQUIRED => '必须的',
            self::ERR_CODE_INPUT_TYPE     => '类型错误',
            self::ERR_CODE_CHECK_REFER    => 'Refer验证',
        );
    
        /**
         * Validator   @desc   成批验证输入
         * @param $arrInput
         *                            array(
         *                            'k1'=>'v1',
         *                            'k2'=>'v2',
         *                            'k3'=>'v3',
         *                            );
         * @param $arrValidationRule
         *                            支持两种验证规则输入格式  字符串传参 和 输出传参
         *
         * 字符串传参
         * array(
         *    'k1'=>'required|type=string|format=date|pattern=#^1[3456789]\d{9}$#|min=1|max=1|enum=1,2,3|nameCn=中文名称',
         *    'k2'=>'type=string',
         *    'k3'=>'enum=1,2,3',
         * );
         *    ||   ||   ||
         * 输出传参
         * array(
         *     'k1'=>array(
         *         'required',
         *         'type'=>'string',
         *         'format'=>'date',
         *         'pattern'=>'#^1[3456789]\d{9}$#',
         *         'min'=>'1',
         *         'max'=>'2',
         *         'enum'=>array('1','2','3'),
         *     ),
         *     'k2'=>array(
         *         'type'=>'string'
         *     ),
         *     'k3'=>array(
         *         'enum'=>array('1','2','3'),
         *     ),
         * );
         * @param bool $checkRequired 是否进行必要验证
         * @param bool $isGetMessage  是否返回message false 不返回
         * @return array|bool
         */
        static public function ValidatorInput($arrInput, $arrValidationRule, $checkRequired = true, $GetMessage = false) {
            $errMessages = array();
    
            foreach ($arrValidationRule as $key => $val) {
                try {
                    $arrRules = self::ruleTransform($val);
                    $name = (isset($arrRules['nameCn']) && (!empty($arrRules['nameCn']))) ? $arrRules['nameCn'] : $key;
    
                    //是否需要进行必要的参数校验
                    if (($checkRequired === true) && isset($arrRules['required'])) {
                        $value = isset($arrInput[$key])?$arrInput[$key]:'';
                        $checkRequired = self::requiredValidator($value,true);
                        if (!$checkRequired) {
                            throw new Exception(self::$MSG[self::ERR_CODE_INPUT_REQUIRED] . "[$name]", self::ERR_CODE_INPUT_REQUIRED);
                        }
                    }
    
                    //如果$arrInput数组存在该参数 对该参数进行格式校验
                    if (isset($arrInput[$key]) && ($arrInput[$key] !== '')) {
                        self::ValidatorInputRow( $arrInput[$key],$arrRules, $key);
                    }
    
                } catch (Exception $e) {
                    $code = $e->getCode();
                    $message = $e->getMessage();
    
                    if ($GetMessage === false) {
                        throw new Exception($message, $code);
                    }
    
                    $errMessages[$key] = array(
                        'code'    => $code,
                        'message' => $message,
                    );
                }
            }
            return $errMessages;
        }
    
        /**
         * ValidatorInputRow   @desc  单条验证
         * @param $rules
         *               array(
         *               'required',
         *               'type'=>'string',     enum[integer|number,string]
         *               'format'=>'date',
         *               'pattern'=>'#^1[3456789]\d{9}$#',
         *               'min'=>'1',
         *               'max'=>'2',
         *               'enum'=>array('1','2','3'),
         *               'nameCn'=>'中文名称',
         *               ),
         *               date-time    2016-09-18 12:12:12
         *               date     2016-09-18
         *               time     12:12:12
         *               utc-millisec     [>=0]
         *               ‘color’  ‘maroon’, ‘red’, ‘orange’, ‘yellow’, ‘olive’, ‘green’, ‘purple’, ‘fuchsia’, ‘lime’, ‘teal’, ‘aqua’, ‘blue’, ‘navy’, ‘black’, ‘gray’, ‘silver’, ‘white’  颜色值
         *               style
         *               phone
         * @param $value 验证的值
         * @param $name  字段名称
         * @throws Exception
         * @return bool
         */
        static public function ValidatorInputRow($value,$rules, $name) {
            $rules = self::ruleTransform($rules);
            $name = isset($rules['nameCn']) ? $rules['nameCn'] : $name;
            $typeRow = isset($rules['type']) ? $rules['type'] : 'string';
    
    
    
            if(isset($rules['required'])){
                self::checkFormat($value, 'required', $name);
                unset($rules['required']);
            }
    
            if(isset($rules['type'])){
                self::checkFormat($value, $typeRow, $name);
                unset($rules['type']);
            }
    
            foreach ($rules as $key => $val) {
                switch ($key) {
                    case 'format':
                        self::checkFormat($value, $val, $name);
                        break;
                    case 'pattern':
                        if (!preg_match($val, $value)) {
                            $msg = sprintf('参数 [%s] 与指定的规则不匹配', $name);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                        break;
                    case 'min':
                        if (($typeRow === 'integer') || ($typeRow === 'int') || ($typeRow === 'number')) {
                            if (intval($value) < (intval($val))) {
                                $msg = sprintf('参数 [%s] 最小值为[%s]', $name, $val);
                                throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                            }
                        } else {
                            if (mb_strlen($value, 'UTF8') < ((int)$val)) {
                                $msg = sprintf('参数 [%s] 最小长度为[%s]', $name, $val);
                                throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                            }
                        }
                        break;
                    case 'max':
                        if (($typeRow === 'integer') || ($typeRow === 'int') || ($typeRow === 'number')) {
                            if (intval($value) > (intval($val))) {
                                $msg = sprintf('参数 [%s] 最大值为[%s]', $name, $val);
                                throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                            }
                        } else {
                            if (mb_strlen($value, 'UTF8') > ((int)$val)) {
                                $msg = sprintf('参数 [%s] 最大长度为[%s]', $name, $val);
                                throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                            }
                        }
                        break;
                    case 'enum':
                        if (!in_array($value, $val)) {
                            $msg = sprintf('参数 [%s] 不是有效的输入', $name);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                        break;
                    default:
                }
            }
            return true;
        }
    
    
        /**
         * checkFormat   @desc  检测数值的数据类型
         * @param $value
         * @param $type
         * @param $valueName
         * @return bool
         * @throws Exception
         */
        public static function checkFormat($value, $type, $valueName = '') {
            $valid = true;
            switch ($type) {
                case 'string':
                    if (is_string($value)) {
                        $xssEntity = self::xssValidator($value);
                        if ($xssEntity != $value) {
                            $msg = sprintf('[%s]对应的数值非法(存在跨站脚本攻击)', $valueName);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                    } else {
                        $valid = false;
                    }
                    break;
                case 'int':
                case 'integer':
                    if ((!is_numeric($value)) || ($value != (int)$value)) {
                        $valid = false;
                    }
                    break;
                case 'number':
                    if (!is_numeric($value)) {
                        $valid = false;
                    }
                    break;
                case 'phone':
                    if (!preg_match('#^1[3456789]\d{9}$#', $value)) {
                        $valid = false;
                    }
                    break;
                case 'uri':
                    if (!preg_match('#^[A-Za-z0-9:/;,\-_\?&\.%\+\|\#=]*$#', $value)) {
                        $valid = false;
                    }
                    break;
                case 'date-time':
                    if (!preg_match('#^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}$#', $value)) {
                        $valid = false;
                    }
                    break;
                case 'date':
                    if (!preg_match('#^\d{4}-\d{2}-\d{2}$#', $value)) {
                        $valid = false;
                    }
                    $type = 'xxxx-xx-xx';
                    break;
                case 'time':
                    if (!preg_match('#^\d{2}:\d{2}:\d{2}$#', $value)) {
                        $valid = false;
                    }
                    break;
                case 'utc-millisec':
                    if ($value < 0) {
                        $valid = false;
                    }
                    break;
                case 'color':
                    $arrColor = array(
                        'maroon',
                        'red',
                        'orange',
                        'yellow',
                        'olive',
                        'green',
                        'purple',
                        'fuchsia',
                        'lime',
                        'teal',
                        'aqua',
                        'blue',
                        'navy',
                        'black',
                        'gray',
                        'silver',
                        'white',
                    );
                    if (!in_array($value, $arrColor)) {
                        if (!preg_match('#^\#[0-9A-F]{6}$#', $value) && !preg_match('#^\#[0-9A-F]{3}$#', $value)) {
                            $valid = false;
                        }
                    }
                    break;
                case 'style':
                    if (!preg_match('#(\.*?)[ ]?:[ ]?(.*?)#', $value)) {
                        $valid = false;
                    }
                    break;
                default:
                    //调用自定义 Validator 类
                    $functionName = "{$type}Validator";
                    if(method_exists(__CLASS__,$functionName)){
                        $valid = self::$functionName($value);
                    }else{
                        $valid = false;
                    }
            }
    
            if (!$valid) {
                $msg = sprintf(' 无效数值 [%s] ,数值格式必须是: [%s]', $valueName, $type);
                throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
            }
            return $valid;
        }
    
        /**
         * ruleTransform   @desc 验证规则转换
         * 如果是字符串规则则转成数组规则
         * @param $rule
         * @return array
         */
        static public function ruleTransform($rule) {
            //字符串验证规则转成数组验证规则
            if (is_array($rule)) {
                $arrRules = $rule;
            } else {
                $arrRule = explode('|', $rule);
                $arrRules = array();
                foreach ($arrRule as $rul) {
                    $arrRul = explode('=', $rul);
                    if (count($arrRul) === 1) {
                        $arrRules[$arrRul[0]] = $arrRul[0];
                    } else if (count($arrRul) === 2) {
                        if ($arrRul[0] === 'enum') {
                            $arrRules[$arrRul[0]] = explode(',', $arrRul[1]);
                        } else {
                            $arrRules[$arrRul[0]] = $arrRul[1];
                        }
                    }
                }
            }
            return $arrRules;
        }
    
        /**
         * requiredValidator   @desc 不能为空验证
         * @param $attribute
         * @param bool $trim
         * @return bool
         */
        public static function requiredValidator($attribute, $trim = true) {
            if(is_array($attribute)){
                $res = empty($attribute)?false:true;
            }elseif(is_string($attribute)){
                $attribute = $trim?trim($attribute):$attribute;
                $res = ($attribute==='')?false:true;
            }else{
                $res = empty($attribute)?false:true;
            }
            return $res;
        }
    
        /**
         * stringValidator   @desc 字符串验证
         * @param $attribute
         * @param $is
         * @return bool
         */
        public static function alphanumericValidator($attribute, $is) {
            $pattern = "/^[a-zA-Z0-9]{" . $is . "}$/";
    
            return preg_match($pattern, $attribute) === 1;
        }
    
        /**
         * emailValidator   @desc 邮件验证
         * @param $attribute
         * @param bool $allowName
         * @return bool
         */
        public static function emailValidator($attribute, $allowName = false) {
            $pattern = "/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/";
            $fullPattern = "/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/";
    
            $valid = preg_match($pattern, $attribute) || $allowName && preg_match($fullPattern, $attribute);
            return $valid;
        }
    
        /**
         * speCharValidator   @desc 特殊字符验证
         * @param $attribute
         * @return bool
         */
        public static function speCharValidator($attribute) {
            $pattern = "/[`~!@#\$%\^&\*\(\)\+=\{\}':;\[\],\.<>|\x{FF01}\x{FFE5}\x{2026}\x{FF08}\x{FF09}\x{2014}\x{3010}\x{3011}\x{2018}\x{2019}\x{201C}\x{201D}\x{FF1A}\x{FF1B}\x{FF0C}\x{3002}\x{3001}\x{FF1F}\x{300A}\x{300B}]+/u";
            return preg_match($pattern, $attribute) === 1;
        }
    
    
        /**
         * companyPhoneValidator   @desc 验证固话
         * @param $companyPhone
         * @return bool
         * @throws Exception
         */
        public static function companyPhoneValidator($companyPhone) {
            $match_res = preg_match("/^\d{3,4}[|-]\d+$/", $companyPhone);
            if (!$match_res) {
                throw new Exception('固定电话格式错误', self::ERR_CODE_INPUT_ERROR);
            } else {
                return true;
            }
        }
    
        /**
         * mobilenumberValidator   @desc 验证手机号
         * @param $mobilenumber
         * @return bool
         */
        public static function mobileNumberValidator($mobilenumber) {
            $match_res = preg_match("/^1[34578]\d{9}$/", $mobilenumber);
    
            if (!$match_res) {
                return false;
            } else {
                return true;
            }
        }
    
        /**
         * cardValidator   @desc 银行卡号
         * @param $cardNo
         * @return bool
         * @throws Exception
         */
        public static function cardValidator($cardNo) {
            $match_res = preg_match("/^\d{16,19}$/", $cardNo);
            if (!$match_res) {
                throw new Exception('银行卡号格式错误', self::ERR_CODE_INPUT_ERROR);
            } else {
                return true;
            }
        }
    
        /**
         * passwordValidator   @desc 密码复杂度验证
         * @param $passwd
         * @param null $prcid
         * @throws Exception
         */
        public static function passwordValidator($passwd, $prcid = null) {
            $match_res = preg_match("/^[0-9]{6}$/", $passwd);
            if (!$match_res) {
                throw new Exception('密码必须是6为数字', self::ERR_CODE_INPUT_ERROR);
            }
    
            $match_res = preg_match("/(\d)(\\1){2}/ie", $passwd);
            if ($match_res) {
                throw new Exception('密码不可以包含3个或以上相同的数字', self::ERR_CODE_INPUT_ERROR);
            }
            $arrVarPassWd = array('012', '123', '234', '345', '456', '567', '678', '789', '890');
            for ($i = 0; $i < 4; $i++) {
                $subpasswd = substr($passwd, $i, 3);
                if (strstr('0123456789', $subpasswd) !== false) {
                    throw new Exception('密码不可以包含3个或以上连续的数字(例如123)', self::ERR_CODE_INPUT_ERROR);
                }
                if (strstr('9876543210', $subpasswd) !== false) {
                    throw new Exception('密码不可以包含3个或以上连续的数字(例如123)', self::ERR_CODE_INPUT_ERROR);
                }
            }
            if ($prcid != null && strstr($prcid, $passwd) !== false) {
                throw new Exception('密码不可以是身份证号的一部分', self::ERR_CODE_INPUT_ERROR);
            }
        }
    
        /**
         * 图片上传验证
         * @param string $base64
         * @return boolean
         */
        public static function base64ImageValidator($base64Image) {
            if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64Image)) {
                return true;
            } else {
                return false;
            }
        }
    
        /**
         * xssValidator   @desc xss 过滤
         * @param $data
         * @param int $htmlentities
         * @return mixed|string
         */
        public static function xssValidator($data, $htmlentities = 0) {
            $htmlentities && $data = htmlentities($data, ENT_QUOTES, 'utf-8');
    
            // Fix &entity\n;
            $data = str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $data);
            $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
            $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
            $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
    
            // Remove any attribute starting with "on" or xmlns
            $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
    
            // Remove javascript: and vbscript: protocols
            $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"\\\\]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
            $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"\\\\]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
            $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"\\\\]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
    
            // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
            $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"\\\\]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
            $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"\\\\]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
            $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"\\\\]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
    
            // Remove namespaced elements (we do not need them)
            $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
    
            do {
                // Remove really unwanted tags
                $old_data = $data;
                $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
            } while ($old_data !== $data);
    
            // we are done...
            //$data = self::filter_remote_img_type($data, false);
            return $data;
        }
    
    
        /**
         * @param $strParam 过滤特殊字符
         * @return mixed
         */
        public static function replaceSpecialChar($strParam) {
            $regex = "/\/|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|/";
            return preg_replace($regex, "", $strParam);
        }
    
        /**
         * sql 注入 字符串过滤
         * @param $strData
         * @return mixed
         */
        public static function injectCheckMysql($strData) {
            return preg_replace('(select|inert|update|delete|from|\'|\/\*|\*|\.\.\/|\.\/|UNION|into|load_file|outfile)', '', $strData);
        }
    
    
        /**
         * 检查Refer
         * @param string $method //方法名
         * @return boolean
         * @assert ( 'ajaxcomment' ) == true
         */
        public static function checkRefer($method = '') {
            $refConfig = Bd_Conf::getAppConf('referer');
            //判断checkref 是否开启状态
            if ($refConfig['checkRefererSwitch'] != 1) {
                return true;
            }
            //ref 为空 抛出异常
            if (empty($_SERVER['HTTP_REFERER'])) {
                throw new Exception(self::getMsg(self::ERR_CODE_CHECK_REFER), self::ERR_CODE_CHECK_REFER);
            }
            //获取conf 信息
            if (isset($refConfig['conf'][$method]) && count($refConfig['conf'][$method]) > 0) {
                $refList = $refConfig['conf'][$method];
            } elseif (isset($refConfig['conf']['default']) && count($refConfig['conf']['default']) > 0) {
                $refList = $refConfig['conf']['default'];
            } else {
                $refList = array();
            }
    
            //循环获取list
            if (!empty($refList)) {
                $ref = &$_SERVER['HTTP_REFERER'];
                if (strpos($ref, 'http://') !== 0 && strpos($ref, 'https://') !== 0) {
                    $ref = 'http://' . $ref;
                }
                foreach ($refList as $item) {
                    preg_match($item, $ref, $arrPregMatch);
                    if (count($arrPregMatch) > 0) {
                        return true;
                    }
                }
                //未匹配上正则 直接抛出异常
                throw new Exception(self::getMsg(self::ERR_CODE_CHECK_REFER), self::ERR_CODE_CHECK_REFER);
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:表单验证类 PHP

          本文链接:https://www.haomeiwen.com/subject/zjmrtxtx.html