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

时间:2018-02-05 17:24:11

标签: php jquery validation yii2 yii-validation

我想制作自定义验证功能,如内置验证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规则。

1 个答案:

答案 0 :(得分:1)

虽然您可以在您的方案中使用Conditional Validators when whenClient ,但我建议您使用更复杂的方式这是为了定义自定义验证器,因为根据文档

  

要创建支持客户端验证的验证器,您应该这样做   实施yii\validators\Validator::clientValidateAttribute()   返回一段执行该代码的JavaScript代码的方法   在客户端进行验证。在JavaScript代码中,您可以使用   以下预定义变量:

     

attribute: 要验证的属性的名称。

     

value: 正在验证的值。

     

messages: 用于保存属性验证错误消息的数组。

     

deferred: 可以推送延迟对象的数组(在下一小节中进行了解释)。

所以你需要做的就是创建一个验证器,并根据你想要的字段将它添加到你的规则中。

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

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+我们会将该逻辑移到验证器中

现在在AgeValidator.php目录中创建一个文件components,如果你使用basic-app在项目的根目录中添加文件夹components,如果它不存在创建一个新的,并在里面复制以下代码。

但是

我假设上面提供的模型名称,如果不是实际名称,则必须在javascript函数中的clientValidateAttribute语句中更新字段名称,如下所示验证器,因为id中字段的ActiveForm属性是以#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;
    }

}