Yii2框架 - Ajax表单中的电子邮件验证

时间:2015-08-03 14:08:37

标签: yii2

我在验证数据库中提交的电子邮件地址是否唯一时遇到问题。 当用户注册时,我需要验证电子邮件地址是否存在,所有其他验证工作正常。

在Yii 2中验证使用Ajax表单时是否缺少步骤。

用户点击CTA在网站/索引上注册

use yii\bootstrap\Modal;
use frontend\models\Register;
use yii\helpers\Html;
use yii\helpers\Url;

...

Modal::begin([
    'id' => 'modal',
    'size'=>'modal-lg',
    'clientOptions' => ['backdrop' => 'static', 'keyboard' => FALSE],
]);

echo "<div id='modalContent'></div>";

Modal::end();
?>
 <?= Html::button('Register', ['value' => Url::to(['register/create']), 'title' => 'Register', 'class' => 'btn btn-success','id'=>'modalButton']); ?>

这会打开一个模态(注册/创建)

模型注册

class Register extends User
{

...

    public function rules()
{
    return [

        ['Email', 'filter', 'filter' => 'trim'],
        ['Email', 'required'],
        ['Email', 'email'],
        ['Email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],

    ];
}

    public function signup()
{
    $user = new User();
    if ($this->validate()) {
        $user->Email            = $this->Email;
        if ($user->save()) {
            return $user;
        }
    } else {
        return;
    }
}

注册控制器

    public function actionCreate()
{
    $model = new Register(['scenario' => 'signup']);
    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        Yii::error($model);
        return $model->validate();
    }
    if ($model->load(Yii::$app->request->post())) {
        if ($user = $model->signup()) {
            if (Yii::$app->getUser()->login($user)) {
                return $this->goHome();
            }
        }
    }
    return $this->renderAjax('create', [
        'model' => $model,
    ]);
}

查看文件

<?php $form = ActiveForm::begin(['id'=> 'register', 'enableClientValidation'=>true, 'enableAjaxValidation'=>true, 'validateOnChange'=> true, 'validationUrl' => Url::to(['register/create'])]  ); ?>
 <div class="form-group">
            <?= $form->field($model, 'Email') ?>
 </div>

Javascript文件

$script = <<< JS

$('body').on('beforeSubmit', 'form#register', function (event, jqXHR, settings) {
     var form = $(this);
     // return false if form still have some validation errors
     if (form.find('.has-error').length) {
          return false;
     }
     // submit form
     $.ajax({
          url: form.attr('action'),
          type: 'GET',
          data: form.serialize(),
          success: function (response) {
               // do something with response

               $(document).find('#modal').modal('hide');
          }
     });
     return false;
});


JS;
$this->registerJs($script);

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,我的电子邮件字段没有触发&#34;独特的&#34;规则在javascript验证中,但&#34;唯一&#34;规则在表单提交时被触发。

很棒的是你提出了一个解决问题的方法来完成工作,但我认为我刚刚学到的东西也可以为其他人提供一些关于这个问题的见解。

对我而言,关键在于学习/认识到&#34;独特的&#34;验证规则必须使用数据库查找来验证用户输入是否唯一,因此必须使用ajax。其他验证规则,例如&#34; required&#34;或者&#34;电子邮件&#34;不需要ajax来验证。他们只是在客户端使用javascript进行验证,因此它们是客户端验证,而&#34; unique&#34;验证器实际上是ajax验证。

注意:下面的代码并不是直接解决您的代码,而是旨在传达回答您的问题所需的整体理解和代码结构。您已经拥有的其中一些步骤,但有些步骤丢失了:)

首先,您需要一个具有字段的模型,该字段需要一个独特的&#39;规则,例如用户帐户的电子邮件地址。

在您的模型中

public function rules()
{
    $rules = [
        [['email'], 'unique'],

        // ... and all your other rules ...
    ];
}

使用\yii\widgets\ActiveForm时,默认情况下会启用客户端验证,但不会启用ajax验证。

因此,接下来您需要在视图中直接启用ajax验证。这可以针对整个表单进行,也可以针对单个字段进行。 Yii2 Validation docs解释得最好,但在我的情况下,我选择在我的电子邮件字段中启用ajax验证。

在您的视图中

<?php $form = ActiveForm::begin(); ?>

<?= $form->field($user, 'email', ['enableAjaxValidation' => true])->textInput();

//... other form fields and such here ...

<?php ActiveForm::end(); ?>

接下来,您还需要在控制器中处理ajax验证,因此您的控制器方法可能如下所示:

public function actionRegister()
{
    $user = new User();

    $post = Yii::$app->request->post();
    $userLoaded = $user->load($post);

    // validate for ajax request
    if (Yii::$app->request->isAjax) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        return ActiveForm::validate($user);
    }

    // vaidate for normal request
    if ($userLoaded && $user->validate()) {
        $user->save();
        return $this->redirect(['view', 'id' => $user->id]);
    }

    // render
    return $this->render('create', ['user' => $user]);
}

然后就是抓住......上面的所有内容都是使用普通(非ajax)形式时所需要的。在您的问题中,您正在处理通过ajax提交的模式窗口中的表单,因此上述控制器方法将不起作用。使用ajax表单,在同一个控制器方法中处理ajax表单验证和ajax表单提交变得非常棘手。

像往常一样,Yii已经为我们解决了这个问题,validationUrl表单参数将节省一天。您所要做的就是在控制器中创建一个专门用于ajax验证的新方法,并在表单中引用控制器/操作URL。这样的事情可以解决问题:

在您的视图中

<?php $form = ActiveForm::begin([
    'id' => 'form-id', // always good to set a form id, especially when working with ajax/pjax forms
    'validationUrl' => ['user/validate-email'], //['controller/action'],
]); ?>

在您的控制器

public function actionRegister()
{
    $user = new User();

    $post = Yii::$app->request->post();

    // vaidate for normal request
    if ($user->load($post) && $user->validate()) {
        $user->save();
        return $this->redirect(['view', 'id' => $user->id]);
    }

    // render
    return $this->render('create', ['user' => $user]);
}

public function actionValidateEmail()
{
    // validate for ajax request
    if (Yii::$app->request->isAjax) {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $user = new User();
        $post = Yii::$app->request->post();
        $user->load($post);

        return ActiveForm::validate($user);
    }       
}

干杯!

答案 1 :(得分:0)

我设法通过使用Javascript发出Ajax请求和PHP来接收任务并检查数据库中是否已存在电子邮件来解决这个问题。

    function checkEmail(){
    var email_check;
    // Get the value of the email input field
    var input_value = document.getElementById('register-email').value;
    // Send the value to a PHP page to check
    $.ajax({
        url: 'checkemail.php/', 
        type: 'POST',
        data: {
        email_check: input_value
    },
        success: function(response) {
            // If we have a repsonse we need to check whether it is True or False
            email_check = response;
            if (email_check == 1) {
                // If True add error class
                $('.field-register-email').addClass('has-error');
                $('.field-register-email .help-block').text('The email supplied has already been used');
            } else {
                $('.field-register-email').removeClass('has-error');
                $('.field-register-email .help-block').text(' ');
            }
        }
    });
};

这将向checkemail.php发送一个POST请求,该请求将检查电子邮件地址是否在数据库中