Yii2验证器(Validator)用法分析

2019-09-03 15:41:50 浏览数 (1)

先看一下验证器的使用。

public function rules()

{

return [

[['email', 'password'], 'required'],

['password', 'string', 'min'=>6],

];

}

如上所示,验证器主要使用在rules里面,对当前model里面的属性值进行验证以检查是否满足某种要求。

验证器使用格式:

书写格式为:[需要验证的属性,验证器名称,验证器参数]。

如果需要验证的属性为多个可用数组,如果为一个属性可用字符串也可用数组来表示。

每个属性都可以有多个验证器,如上面的password使用了 required和string两个验证器。

常用验证器:

Yii2已经内置了一些常用的验证器。所有的验证器都从基类yiivalidatorsValidator继承实现。我大概总结下有这么几类。

数字相关:

integer——整数 用来检测属性值是否为整数,以及最大、最小值检测等。(yiivalidatorsNumberValidator)

double——浮点 用来检测属性值是否为浮点数,即小数。(yiivalidatorsNumberValidator)

number——数字 这个和上面的double完全相同,只是用了2个名称。(yiivalidatorsNumberValidator)

格式相关:

date——日期 检验属性值是否为正确的日期格式。(yiivalidatorsDateValidator)

email——邮件 检测属性值是否是正确的电子邮件格式。(yiivalidatorsEmailValidator)

url——URL 用来判断属性值是否是正确的url地址。(yiivalidatorsUrlValidator)

对值进行函数处理:

filter——过滤器 这个是对属性值进行加工处理的。如对属性值加前缀、替换特定的字符串等等。(yiivalidatorsFilterValidator)

trim——裁边 这个是对属性值进行加工处理的。只是去掉字符串两侧的空格、或指定的字符串。(yiivalidatorsFilterValidator)

上传文件验证:

file——文件 这个主要是对上传的文件进行验证,如格式、大小等。(yiivalidatorsFileValidator)

image——图片 这个和上面的file验证器差不多,不过是专门用来验证图片的。(yiivalidatorsImageValidator)

判断比较:

compare——比较 用来对两个属性值进行比较,如相等、大于、小于比较等。(yiivalidatorsCompareValidator)

in——包含(范围) 用来检测属性值是否包含在指定的数组中。(yiivalidatorsRangeValidator)

exist——存在 用来检测在数据表中是否已经存在此属性值。(yiivalidatorsExistValidator)

unique——唯一性 这个和exist差不多,用来检测值是否是唯一。(yiivalidatorsUniqueValidator)

string——字符串 对属性值进行长度判断,如最大长度、最短长度等。(yiivalidatorsStringValidator)

boolean——布尔型 用来检查属性的值是否为布尔值。(yiivalidatorsBooleanValidator)

default——默认值 这个是用来给属性设置默认值的。如当属性值为null的时候,给它设置为 空的默认值。(yiivalidatorsDefaultValueValidator)

required——必填 这个用来检查属性值是否为空。(yiivalidatorsRequiredValidator)

captcha——验证码 这个主要是在界面使用验证码的时候对验证码进行验证的。(yiicaptchaCaptchaValidator)

match——正则表达式 这个就比较强大了,用来检测属性值是否匹配给出的正则。上面所列出的基本都可以用这个实现。(yiivalidatorsRegularExpressionValidator)

其它:

safe——安全 这个不进行验证,仅仅用来指定属性值是安全的。(yiivalidatorsSafeValidator)

--------------------------

ii2的Validator是非常好用的一类方法,它辅助Model层,完成对数据的校验。现在核心的验证器有这么几类:

代码语言:javascript复制
BooleanValidator - 要求属性必须为Bool类型
CompareValidator - 完成两个属性的比较
DateValidator - 要求属性必须为日期类型
EachValidator - 要求数组的每个元素必须满足某个条件
EmailValidator - 要求属性必须为邮件格式
ExistValidator - 要求该属性必须存在于此模型或者别的模型个某个属性当中
StringValidator - 要求该属性必须为字符串
RangeValidator - 要求属性必须在某个范围之内取值
.....

使用起来,它们都有一样的面孔,那就是,在复写的model::rules方法里面增加一条规则:

代码语言:javascript复制
['country', 'in', 'range' => ['china', 'usa'], 'message' => 'the country is wrong']

这条规则就可以保证country这个属性必须在china和usa之间二选一,否则就会报'the country is wrong'错误。是不是非常的简单? 这个家族的验证器在活动记录ActiveRecord的使用时非常有用,能保证你插入数据库的数据是正确无误的。 已有的校验类虽然很丰富,但是毕竟不能满足我们全部的对数据校验需求,我们希望能扩展已有的验证器。有没有这样一个方法,既能能以这样简单的方式使用,又能方便我们自己定义校验规则?这就是今天要跟大家分享的内容。 直接上代码:

代码语言:javascript复制
class RegexValidator extends Validator
{
    /**
     * @var string|array 所要采用的验证方法,可以为string,也可以为如果个方法组成的array
     * 所有的方法必须属于RegexValidator
     */
    public $method = null;
    /**
     * @var array 验证的方法列表
     * 方法必须属于RegexValidator
     */
    private $_methodArray = [];

    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
        $this->_methodArray = (array)$this->method;
        if(empty($this->_methodArray)){
            throw new InvalidConfigException("Configuration error:no validating method are found!");
        }
        foreach($this->_methodArray  as $method){
            if(!$this->hasMethod($method)){
                throw new InvalidConfigException("Validating method:"{$method}" does not exits!");
            }
        }
    }

    /**
     * @inheritdoc
     */
    public function validateAttribute($model, $attribute)
    {
        $value = $model->$attribute;
        //将错误信息转化为数组,数组元素对应[_methodArray]的验证方法
        $this->message = (array)$this->message;
        foreach($this->_methodArray  as $k => $method){
            $ret = call_user_func([$this, $method], $value);
            if($ret === false){
                $error = isset($this->message[$k]) ? $this->message[$k] : Yii::t('yii', '{attribute} is invalid.');
                $this->addError($model, $attribute, $error);
            }
        }
    }

    /**
     * @inheritdoc
     */
    protected function validateValue($value)
    {
        $this->message = (array)$this->message;
        foreach($this->_methodArray as $k => $method){
            $ret = call_user_func([$this, $method], $value);
            if($ret === false){
                $error = isset($this->message[$k]) ? $this->message[$k] : Yii::t('yii', ""{$value}" is invalid specified by the validator:". static::className() ."::$method");
                return [$error, []];
            }
        }
        return null;
    }

    /**
     * @inheritdoc
     */
    public function clientValidateAttribute($model, $attribute, $view)
    {

    }   

   //...这里是你的逻辑…… 
   
    /**
     * 由26个大写英文字母组成的字符串
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function uperchars($data = null)
    {
        $_pattern = "/^[A-Z] $/";
        return self::_regex($_pattern, $data);
    }

    /**
     * 由26个小写写英文字母组成的字符串
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function lowerchars($data = null)
    {
        $_pattern = "/^[a-z] $/";
        return self::_regex($_pattern, $data);
    }

    /**
     * 由数字和26个英文字母组成的字符串
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function numschars($data = null)
    {
        $_pattern = "/^[A-Za-z0-9] $/";
        return self::_regex($_pattern, $data);
    }

    /**
     * 手机号码
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function mobile($data = null)
    {
        $_pattern = "/^(0|86|17951)?(13[0-9]|15[012356789]|1[78][0-9]|14[57])[0-9]{8}$/";
        return self::_regex($_pattern, $data);
    }

    /**
     * Email
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function email($data = null)
    {
        $_res = filter_var($data, FILTER_VALIDATE_EMAIL);
        return empty($_res) ? false : true;
    }

    /**
     * 邮编
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function postcode($data = null)
    {
        $_pattern = "/^[1-9]d{5}(?!d)$/";
        return self::_regex($_pattern, $data);
    }

    /**
     * 中文
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function zh($data = null)
    {
        $_pattern = "/^[x{4e00}-x{9fa5}] $/u";
        return self::_regex($_pattern, $data);
    }

    /**
     * URL地址
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function url($data = null)
    {
        $_res = filter_var($data, FILTER_VALIDATE_URL);
        return empty($_res) ? false : true;
    }

    /**
     * 身份证
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function identity($data = null)
    {
        $_pattern = "/^(^d{15}$)|(^d{17}([0-9]|X)$)$/";
        return self::_regex($_pattern, $data);
    }

    /**
     * IPv4
     * @param $data mixed 数字或者字符串
     * @return bool
     **/
    public static function ip($data = null)
    {
        $_res = filter_var($data, FILTER_VALIDATE_IP);
        return empty($_res) ? false : true;
    }

    /**
     * 匹配正则公共方法
     * @param $pattern string 匹配模式
     * @param $subject string 对象
     * @return bool
     */
    private static function _regex($pattern, $subject = null)
    {
        if ($subject === null)
        {
            return false;
        }
        if (preg_match($pattern, $subject))
        {
            return true;
        }
        return false;
    }

}

首先,必须继承yiivalidatorsValidator,并且复写validateAttributevalidateValue方法。validateAttribute是验证属性用的,调用$module->validate()时会对其隐式的调用;validateValue则可以不依赖Model独立使用。clientValidateAttribute则是在客户端实现数据校验的部分(这部分等待聪明的你去DIY)。init实现初始化的功能。 复写了基础的几个Validator方法,然后就是我们自己的校验数据的逻辑:

代码语言:javascript复制
zh - 校验数据是否为中文
postcode - 校验数据是否为邮编
mobile - 校验数据是否为手机号码
……

接下来,当然是最精彩的部分——如何使用?有三种方式可以方便您调用:

1.用在数据模型model的rules方法里面:

代码语言:javascript复制
['name', RegexValidator::className(), 'method' => 'lowerchars', 'message' => '名字必须全为小写字母']
[
    ['mobile', 'status'],
    RegexValidator::className(),
    'method' => ['mobile', 'zh'],
    'message' => ['手机格式不正确', '必须为中文']
]

这里需要在Model里引入RegexValidator类,并用RegexValidator::className()代替核心验证器'in','string','exsit'等; 规则里的'method'是你自己定义的(静态)方法,你的校验逻辑之所在。可以单个引用,也可以为数组,当为数组时对应的错误信息'message'也得为数组,而且错误信息与之对应。 当调用$model->validate(),如果不满足以上的条件这个方法就会返回false,而且在$model->getErrors()里面会返回具体的错误信息:

代码语言:javascript复制
[
    'name' => [
        '名字必须全为小写字母',
    ],
    'mobile' => [
        '手机格式不正确',
    ],
    'zh' => [
        '必须为中文',
    ],  
]

返回的错误信息和核心验证器格式是完全一样的。

2.脱离model独立使用,必须要配置[method]参数:

代码语言:javascript复制
$valid = new RegexValidator([
    'method' => ['zh', 'negative'],
    'message' => ['必须为中文', '必须为负数'],
)];
$valid->validate($value, $error);
if($error){
    echo $error;
}

同样的和核心验证器的使用方法相同;

3.直接调用RegexValidator里的各个静态方法进行验证

代码语言:javascript复制
$value = 'Abc';
$ret = RegexValidator::mobile($value);
if(!$ret){
	echo ...;
}

这是最简单调用方法,此时无法使用错误提示。 这个类是可以扩展的,您可以将自己的逻辑在number以降继续添加。

G

M

T

Detect languageAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu

Text-to-speech function is limited to 200 characters

Options : History : Feedback : Donate

Close

0 人点赞