Использование пользовательских валидаторов с ActiveForm в 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 правило, если вы пытаетесь отправить пустое поле.

1 ответ

Решение

Хотя вы можете использовать Conditional Validatorswhen а также whenClient тоже в вашем сценарии, но я бы порекомендовал использовать более сложный способ, который заключается в определении собственного валидатора, потому что в соответствии с документами

Чтобы создать валидатор, который поддерживает валидацию на стороне клиента, вы должны реализовать yii\validators\Validator::clientValidateAttribute() метод, который возвращает фрагмент кода JavaScript, который выполняет проверку на стороне клиента. В коде JavaScript вы можете использовать следующие предопределенные переменные:

attribute: имя проверяемого атрибута.

value: значение проверяется.

messages: массив, используемый для хранения сообщений об ошибках валидации для атрибута.

deferred: массив, в который могут быть помещены отложенные объекты (объяснение в следующем подразделе).

Итак, вам нужно создать валидатор и добавить его в ваши правила для поля, которое вы хотите.

Вы должны быть осторожны, копируя следующий код, если вы не указали фактическое название модели, и соответственно обновите имена полей.

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

}
Другие вопросы по тегам