简体   繁体   English

在Yii2中将自定义验证器与ActiveForm一起使用

[英]Using custom validators with ActiveForm in Yii2

I want to make custom validation function like built-in validation required . 我想进行自定义的验证功能如内置的验证required I have example code here: 我在这里有示例代码:

Model: 模型:

use yii\base\Model;

class TestForm extends Model
{
    public $age;
    public function rules(){
        return [
            ['age', 'my_validation']
        ];
    }
    public function my_validation(){
        //some code here
    }
}

View: 视图:

<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;


$this->title = 'test';
?>
<div style="margin-top: 30px;">

    <?php $form = ActiveForm::begin(); ?>
    <?= $form->field($model, 'age')->label("age") ?>
    <div class="form-group">
        <?= Html::submitButton('submit', ['class' => 'btn btn-primary']) ?>
    </div>
    <?php ActiveForm::end(); ?>

</div>

Controller: 控制器:

use app\models\form\TestForm;
use yii\web\Controller;

class TestController extends Controller
{
    public function actionIndex(){
        $model = new TestForm();

        if($model->load(\Yii::$app->request->post())){
            return $this->render('test', array(
                'model'=>$model,
                'message'=>'success'
            ));
        }
        return $this->render('test', array('model'=>$model));
    }
}

in this example I have a field for age and this my_validation function should check if age is over 18 before submit and throw error if age is under 18. This validation should be processed by ajax like it is in case of required rule if you try to submit empty field. 在此示例中,我有一个年龄字段,该my_validation函数应检查年龄是否超过18岁,如果年龄小于18岁,则将提交提交并引发错误。如果您尝试执行required规则,则应由ajax处理该验证提交空字段。

Although you can use Conditional Validators when and whenClient too in your scenario but I would recommend using a more sophisticated way which is to define a custom validator because according to the docs 尽管您也可以在场景中的whenwhenClient使用whenClient Conditional Validators when但我还是建议您使用更复杂的方法来定义自定义验证器,因为根据文档

To create a validator that supports client-side validation, you should implement the yii\\validators\\Validator::clientValidateAttribute() method which returns a piece of JavaScript code that performs the validation on the client-side. 要创建支持客户端验证的验证器,您应该实现yii\\validators\\Validator::clientValidateAttribute()方法,该方法返回一段JavaScript代码来在客户端执行验证。 Within the JavaScript code, you may use the following predefined variables: 在JavaScript代码中,您可以使用以下预定义的变量:

attribute: the name of the attribute being validated. attribute:要验证的属性的名称。

value: the value being validated. value:正在验证的值。

messages: an array used to hold the validation error messages for the attribute. messages:一个数组,用于保存属性的验证错误消息。

deferred: an array which deferred objects can be pushed into (explained in the next subsection). deferred:可以将延迟对象推入的数组(在下一节中说明)。

So what you need to do is create a validator and add it to your rules against the field you want. 因此,您需要做的是创建一个验证器,并将其添加到您想要的字段的规则中。

You need to be careful copying the following code IF you haven't provided the actual model name and update the field names accordingly. 如果您没有提供实际的型号名称,请仔细复制以下代码,并相应地更新字段名称。

1) First thing to do is to update the ActiveForm widget to the following 1)首先要做的是将ActiveForm小部件更新为以下内容

$form = ActiveForm::begin([
    'id' => 'my-form',
    'enableClientValidation' => true,
    'validateOnSubmit' => true,
]);

2) Change your model rules() function to the following 2)将您的模型rules()函数更改为以下内容

public function rules()
    {
        return [
            [['age'], 'required'],
            [['age'], \app\components\AgeValidator::className(), 'skipOnEmpty' => false, 'skipOnError' => false],
        ];
    }

3) Remove the custom validation function my_validation() from your model i hope you are checking the age limit in it to be 18+ we will move that logic into the validator. 3)从您的模型中删除自定义验证函数my_validation() ,希望您正在检查其中的年龄限制为18+我们将把该逻辑移到验证器中。

Now create a file AgeValidator.php inside components directory, if you are using the basic-app add the folder components inside the root directory of the project if it does not exist create a new one, and copy the following code inside. 现在,在components目录中创建一个文件AgeValidator.php ,如果您使用的是basic-app ,请在项目的根目录中添加文件夹components如果不存在),然后创建一个新文件夹,并在其中复制以下代码。

BUT

I have assumed the name of the Model that is provided by you above so if it not the actual name you have to update the field name inside the javascript statements within clientValidateAttribute function you see below in the validator because the id attribute of the fields in ActiveForm is generated in a format like #modelname-fieldname (all small case) so according to above given model, it will be #testform-age do update it accordingly otherwise the validation wont work. 我已经假设了您上面提供的Model的名称,所以如果不是实际名称,则必须更新在验证器下面看到的clientValidateAttribute函数中的javascript语句内的字段名称,因为ActiveForm中的字段的id属性是以#modelname-fieldname (所有大小写)之类的格式生成的,因此根据上述给定的模型,将#testform-age进行相应的更新,否则验证将无法进行。 And do update the namespace in the validator below and in the model rules() if you plan to save it somewhere else. 如果打算将其保存在其他位置,请在下面的验证器和模型rules()更新名称空间。

<?php

namespace app\components;

use yii\validators\Validator;

class AgeValidator extends Validator
{

    public function init()
    {
        parent::init();
        $this->message = 'You need to be above the required age 18+';
    }

    public function validateAttribute($model, $attribute)
    {

        if ($model->$attribute < 18) {
            $model->addError($attribute, $this->message);
        }
    }

    public function clientValidateAttribute($model, $attribute, $view)
    {

        $message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        return <<<JS

if (parseInt($("#testform-age").val())<18) {
    messages.push($message);
}
JS;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM