1

序言

验证唯一性很重要,说不上用得很普及,但是也必须要有。好比注册功能模块,手机号、邮箱注册这些,肯定是要验证其的唯一性的,重复了登录就会混乱。那么如何使用Yii2自带的targetClass验证唯一性呢?使页面刷新的可能很多人都会,要是不刷新页面直接触发targetClass验证的应该就少些了吧!不会的也不必苦恼,不必担心,因为我写这篇文章的目的就是要告诉你怎么通过页面不刷新的方式直接触发targetClass验证其手机号、邮箱唯一性。

需求分析

1、使用Yii2框架自带的targetClass在不刷新页面的情况下验证手机号、邮箱唯一性。

效果图

这是点击下一步的时候在页面没刷新的情况下出现的验证提示“手机号已经注册”。
图片描述

代码分析

1、配置model,我以注册SignupFrom 的model为例,rules里的代码如下:

 public function rules()
    {
         return [
            ['t_mobile', 'filter', 'filter' => 'trim'],
            ['t_mobile', 'required'],
             //targetClass 不会自己调用Ajax验证,提交表单后才会触发
            ['t_mobile', 'unique', 'targetClass' => '\login\models\User', 'message' => '手机号已经注册。'],
            [['t_mobile'],'match','pattern'=>'/^[1][358][0-9]{9}$/'],
            
            ['t_password','required'],
            ['t_re_password','required'],
            ['t_re_password','compare','compareAttribute'=>'t_password','message'=>'两次密码输入不一致。'],
            ['t_password', 'string', 'min' => 6],
            ['t_re_password', 'string', 'min' => 6],
            ['company_id', 'trim'],
            ['t_realname', 'trim'],
            ['company_id', 'required'],
            ['t_realname', 'required'],
            ['company_id', 'string', 'min' => 2, 'max' => 255],
            ['t_realname', 'string', 'min' => 2, 'max' => 255], 
            ['code', 'required'],
            
            //验证码验证,model自定义验证的写法,也分享给大家了
            ['code', function ($attribute, $params) { 
                $cd=SmsCode::find()->where(['mobile'=>$this->t_mobile,'code'=>$this->$attribute])->one();
                if(!empty($cd->code) && (strtolower($this->$attribute) == strtolower($cd->code))){
                    return true;
                }else{  
                    $this->addError('code','验证码错误。');
                }
            }],

        ];
    }

注释:邮箱和手机号的写法是一样的,区别是pattern的验证规则,如是邮箱验证就换成邮箱的正则匹配符。
2、在Controller里加上如下一段Ajax提交表单验证的代码

       //Ajax表单验证
       if((Yii::$app->request->isAjax && $model->load($post))){

            Yii::$app->response->format=Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        } 

注意:这段代码要放在控制器注册方法的最前面,原因很简单,不可能你所有的操作都完成了再去走验证吧?
3、View层的Ajax验证触发配置
from表单代码如下:

  <?php $form = ActiveForm::begin([
                    'action'=>'signup?id=reg',
                    'id' => 'login-form',
                    'validateOnBlur'=>false,//关闭失去焦点验证
                    'enableAjaxValidation'=>true, //开启Ajax验证
                    'enableClientValidation'=>false //关闭客户端验证
 ]); ?>
    <div id="set_up">
        <h3 class="form-title font-blue">设置用户名</h3>
        <div class="alert alert-danger display-hide">
            <button class="close" data-close="alert"></button>
            <span> Enter any username and password. </span>
        </div>

        <div class="form-group  has-error">
            <!--ie8, ie9 does not support html5 placeholder, so we just show field title for that-->
<!--            <label class="control-label visible-ie8 visible-ie9">Username</label>-->
            <?= $form->field($model, 't_mobile',['inputOptions'=>['class'=>'form-control form-control-solid placeholder-no-fix','placeholder'=>'手机号']])->label('') ?>

        </div>

        <div class="form-actions">

            <?= Html::Button('下一步', ['class' => 'btn blue uppercase', 'name' => 'login-button','id'=>'next']) ?>
           
            <?= Html::a('登录',['/site/login'],['class' => 'forget-password']) ?>

        </div>
    </div>
 

注释:(1)、enableAjaxValidation和enableClientValidation的配置必须是enableAjaxValidation为true,enableClientValidation为false。除此之外id也必须要有。
(2)、上面的点击下一步按钮我使用Button,原因是我的注册功能不是一步走完的,需要好几步,好几个页面才能完成注册,要实现全部无刷新,不能直接使用submitButton提交表单,得自己写Ajax提交。但是如果你们做的注册功能是一个页面实现的话,那就可以直接用submitButton提交表单了。以上的配置Ajax验证已经生效,提交表单页面不刷新的情况下也能直接触发targetClass验证,不必担心验证唯一性的时候页面会刷新了。

常见问题

1、只model里配置targetClass唯一性验证,在View层开启enableAjaxValidation和关闭enableClientValidation验证,没有在Controller里边加上文章中我所说的Ajax提交表单验证的代码,导致Ajax验证不成功。那段代码必须要加的。

相关资料

1、YII2表单验证问题:注册时ajax验证手机号唯一 :http://www.yiichina.com/question/241


zacklee
704 声望56 粉丝