在 Yii2 中使用带有 ActiveForm 的自定义验证器

Using custom validators with ActiveForm in Yii2

我想制作像内置验证一样的自定义验证功能required。我这里有示例代码:

型号:

use yii\base\Model;

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

查看:

<?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>

控制器:

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));
    }
}

在这个例子中,我有一个年龄字段,这个 my_validation 函数应该在提交之前检查年龄是否超过 18 岁,如果年龄低于 18 岁则抛出错误。这个验证应该由 ajax 就像在 required 规则的情况下,如果您尝试提交空字段。

尽管您也可以在您的场景中使用 Conditional Validators whenwhenClient 但是我建议使用更复杂的方法来定义自定义验证器,因为根据文档

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. Within the JavaScript code, you may use the following predefined variables:

attribute: the name of the attribute being validated.

value: the value being validated.

messages: an array used to hold the validation error messages for the attribute.

deferred: an array which deferred objects can be pushed into (explained in the next subsection).

所以您需要做的是创建一个验证器并将其添加到您想要的字段的规则中。

您需要小心复制以下代码如果您没有提供实际型号名称并相应地更新字段名称。

1) 首先要做的是将 ActiveForm 小部件更新为以下

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

2) 将您的模型 rules() 函数更改为以下

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

3) 从您的模型中删除自定义验证函数 my_validation() 我希望您检查其中的年龄限制 18+ 我们将移动该逻辑进入验证器。

现在在 components 目录中创建一个文件 AgeValidator.php,如果您使用 basic-app,请在项目的根目录中添加文件夹 components(如果有的话)不存在新建一个,把下面的代码复制进去

但是

我假定了您上面提供的模型名称,因此如果它不是实际名称,您必须更新 clientValidateAttribute 函数中 javascript 语句中的字段名称,您会看到在下面的验证器中,因为 ActiveForm 中字段的 id 属性是以 #modelname-fieldname 格式生成的(所有小写)所以根据上面给定的模型,它将是 #testform-age 相应地更新它,否则验证将不起作用。如果您打算将命名空间保存在其他地方,请务必在下面的验证器和模型 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;
    }

}