input-validation.md 24.6 KB
Newer Older
Qiang Xue committed
1 2
Validating Input
================
Alexander Makarov committed
3

Qiang Xue committed
4 5
As a rule of thumb, you should never trust the data received from end users and should always validate them
before putting them to good use.
Qiang Xue committed
6

Qiang Xue committed
7 8 9
Given a [model](structure-models.md) populated with user inputs, you can validate the inputs by calling the
[[yii\base\Model::validate()]] method. The method will return a boolean value indicating whether the validation
succeeds or not. If not, you may get the error messages from the [[yii\base\Model::errors]] property. For example,
Qiang Xue committed
10

Qiang Xue committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
```php
$model = new \app\models\ContactForm;

// populate model attributes with user inputs
$model->attributes = \Yii::$app->request->post('ContactForm');

if ($model->validate()) {
    // all inputs are valid
} else {
    // validation failed: $errors is an array containing error messages
    $errors = $model->errors;
}
```

Behind the scene, the `validate()` method does the following steps to perform validation:
Larry Ullman committed
26

Qiang Xue committed
27 28 29 30 31 32 33 34 35 36 37 38 39
1. Determine which attributes should be validated by getting the attribute list from [[yii\base\Model::scenarios()]]
   using the current [[yii\base\Model::scenario|scenario]]. These attributes are called *active attributes*.
2. Determine which validation rules should be used by getting the rule list from [[yii\base\Model::rules()]]
   using the current [[yii\base\Model::scenario|scenario]]. These rules are called *active rules*.
3. Use each active rule to validate each active attribute associated with that rule. If the rule fails,
   keep an error message for the attribute in the model.


## Declaring Rules <a name="declaring-rules"></a>

To make `validate()` really work, you should declare validation rules for the attributes you plan to validate.
This should be done by overriding the [[yii\base\Model::rules()]] method. The following example shows how
the validation rules for the `ContactForm` model are declared:
40

Qiang Xue committed
41 42 43 44 45 46
```php
public function rules()
{
    return [
        // the name, email, subject and body attributes are required
        [['name', 'email', 'subject', 'body'], 'required'],
47

Qiang Xue committed
48 49 50 51 52
        // the email attribute should be a valid email address
        ['email', 'email'],
    ];
}
```
53

Qiang Xue committed
54 55
The [[yii\base\Model::rules()|rules()]] method should return an array of rules, each of which is an array
of the following format:
56

Qiang Xue committed
57 58 59
```php
[
    // required, specifies which attributes should be validated by this rule.
Qiang Xue committed
60
    // For a single attribute, you can use the attribute name directly
Qiang Xue committed
61 62
    // without having it in an array instead of an array
    ['attribute1', 'attribute2', ...],
63

Qiang Xue committed
64 65 66 67 68 69
    // required, specifies the type of this rule.
    // It can be a class name, validator alias, or a validation method name
    'validator',

    // optional, specifies in which scenario(s) this rule should be applied
    // if not given, it means the rule applies to all scenarios
Qiang Xue committed
70 71
    // You may also configure the "except" option if you want to apply the rule
    // to all scenarios except the listed ones
Qiang Xue committed
72 73 74 75 76 77 78
    'on' => ['scenario1', 'scenario2', ...],

    // optional, specifies additional configurations for the validator object
    'property1' => 'value1', 'property2' => 'value2', ...
]
```

Qiang Xue committed
79 80 81 82 83 84 85 86 87
For each rule you must specify at least which attributes the rule applies to and what is the type of the rule.
You can specify the rule type in one of the following forms:

* the alias of a core validator, such as `required`, `in`, `date`, etc. Please refer to
  the [Core Validators](tutorial-core-validators.md) for the complete list of core validators.
* the name of a validation method in the model class, or an anonymous function. Please refer to the
  [Inline Validators](#inline-validators) subsection for more details.
* the name of a validator class. Please refer to the [Standalone Validators](#standalone-validators)
  subsection for more details.
Qiang Xue committed
88

Qiang Xue committed
89 90 91
A rule can be used to validate one or multiple attributes, and an attribute may be validated by one or multiple rules.
A rule may be applied in certain [scenarios](structure-models.md#scenarios) only by specifying the `on` option.
If you do not specify an `on` option, it means the rule will be applied to all scenarios.
Qiang Xue committed
92 93 94 95 96 97 98 99 100 101

When the `validate()` method is called, it does the following steps to perform validation:

1. Determine which attributes should be validated by checking the current [[yii\base\Model::scenario|scenario]]
   against the scenarios declared in [[yii\base\Model::scenarios()]]. These attributes are the active attributes.
2. Determine which rules should be applied by checking the current [[yii\base\Model::scenario|scenario]]
   against the rules declared in [[yii\base\Model::rules()]]. These rules are the active rules.
3. Use each active rule to validate each active attribute which is associated with the rule.

According to the above validation steps, an attribute will be validated if and only if it is
Qiang Xue committed
102
an active attribute declared in `scenarios()` and is associated with one or multiple active rules
Qiang Xue committed
103 104
declared in `rules()`.

Qiang Xue committed
105

Qiang Xue committed
106
### Customizing Error Messages <a name="customizing-error-messages"></a>
Qiang Xue committed
107

Qiang Xue committed
108 109
Most validators have default error messages that will be added to the model being validated when its attributes
fail the validation. For example, the [[yii\validators\RequiredValidator|required]] validator will add
Qiang Xue committed
110
a message "Username cannot be blank." to a model when the `username` attribute fails the rule using this validator.
Qiang Xue committed
111

Qiang Xue committed
112 113
You can customize the error message of a rule by specifying the `message` property when declaring the rule,
like the following,
Qiang Xue committed
114 115 116 117 118

```php
public function rules()
{
    return [
Qiang Xue committed
119
        ['username', 'required', 'message' => 'Please choose a username.'],
Qiang Xue committed
120 121 122 123
    ];
}
```

Qiang Xue committed
124 125 126 127 128
Some validators may support additional error messages to more precisely describe different causes of
validation failures. For example, the [[yii\validators\NumberValidator|number]] validator supports
[[yii\validators\NumberValidator::tooBig|tooBig]] and [[yii\validators\NumberValidator::tooSmall|tooSmall]]
to describe the validation failure when the value being validated is too big and too small, respectively.
You may configure these error messages like configuring other properties of validators in a validation rule.
Qiang Xue committed
129 130


131 132 133 134 135 136 137 138 139 140 141 142 143 144
### Validation Events <a name="validation-events"></a>

When [[yii\base\Model::validate()]] is called, it will call two methods that you may override to customize
the validation process:

* [[yii\base\Model::beforeValidate()]]: the default implementation will trigger a [[yii\base\Model::EVENT_BEFORE_VALIDATE]]
  event. You may either override this method or respond to this event to do some preprocessing work
  (e.g. normalizing data inputs) before the validation occurs. The method should return a boolean value indicating
  whether the validation should proceed or not.
* [[yii\base\Model::afterValidate()]]: the default implementation will trigger a [[yii\base\Model::EVENT_AFTER_VALIDATE]]
  event. You may either override this method or respond to this event to do some postprocessing work after
  the validation is completed.


Qiang Xue committed
145
### Conditional Validation <a name="conditional-validation"></a>
Qiang Xue committed
146

Qiang Xue committed
147 148 149
To validate attributes only when certain conditions apply, e.g. the validation of one attribute depends
on the value of another attribute you can use the [[yii\validators\Validator::when|when]] property
to define such conditions. For example,
Qiang Xue committed
150

Qiang Xue committed
151 152 153 154 155 156 157
```php
[
    ['state', 'required', 'when' => function($model) {
        return $model->country == 'USA';
    }],
]
```
Qiang Xue committed
158

Qiang Xue committed
159
The [[yii\validators\Validator::when|when]] property takes a PHP callable with the following signature:
Qiang Xue committed
160 161

```php
Qiang Xue committed
162 163 164 165 166 167
/**
 * @param Model $model the model being validated
 * @param string $attribute the attribute being validated
 * @return boolean whether the rule should be applied
 */
function ($model, $attribute)
Qiang Xue committed
168 169
```

Qiang Xue committed
170 171 172
If you also need to support client-side conditional validation, you should configure
the [[yii\validators\Validator::whenClient|whenClient]] property which takes a string representing a JavaScript
function whose return value determines whether to apply the rule or not. For example,
Qiang Xue committed
173 174

```php
Qiang Xue committed
175 176 177 178 179 180 181
[
    ['state', 'required', 'when' => function ($model) {
        return $model->country == 'USA';
    }, 'whenClient' => "function (attribute, value) {
        return $('#country').value == 'USA';
    }"],
]
Qiang Xue committed
182 183 184
```


Qiang Xue committed
185
### Data Filtering <a name="data-filtering"></a>
Qiang Xue committed
186

Qiang Xue committed
187
User inputs often need to be filtered or preprocessed. For example, you may want to trim the spaces around the
Qiang Xue committed
188 189 190 191
`username` input. You may use validation rules to achieve this goal.

The following examples shows how to trim the spaces in the inputs and turn empty inputs into nulls by using
the [trim](tutorial-core-validators.md#trim) and [default](tutorial-core-validators.md#default) core validators:
Qiang Xue committed
192

Qiang Xue committed
193 194
```php
[
Qiang Xue committed
195 196
    [['username', 'email'], 'trim'],
    [['username', 'email'], 'default'],
Qiang Xue committed
197 198
]
```
Qiang Xue committed
199

Qiang Xue committed
200 201
You may also use the more general [filter](tutorial-core-validators.md#filter) validator to perform more complex
data filtering.
Qiang Xue committed
202

Qiang Xue committed
203 204
As you can see, these validation rules do not really validate the inputs. Instead, they will process the values
and save them back to the attributes being validated.
Qiang Xue committed
205

Qiang Xue committed
206

Qiang Xue committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
### Handling Empty Inputs <a name="handling-empty-inputs"></a>

When input data are submitted from HTML forms, you often need to assign some default values to the inputs
if they are empty. You can do so by using the [default](tutorial-core-validators.md#default) validator. For example,

```php
[
    // set "username" and "email" as null if they are empty
    [['username', 'email'], 'default'],

    // set "level" to be 1 if it is empty
    ['level', 'default', 'value' => 1],
]
```

By default, an input is considered empty if its value is an empty string, an empty array or a null.
You may customize the default empty detection logic by configuring the the [[yii\validators\Validator::isEmpty]] property
with a PHP callable. For example,

```php
[
    ['agree', 'required', 'isEmpty' => function ($value) {
        return empty($value);
    }],
]
```

> Note: Most validators do not handle empty inputs if their [[yii\base\Validator::skipOnEmpty]] property takes
  the default value true. They will simply be skipped during validation if their associated attributes receive empty
  inputs. Among the [core validators](tutorial-core-validators.md), only the `captcha`, `default`, `filter`,
  `required`, and `trim` validators will handle empty inputs.


Qiang Xue committed
240
## Ad Hoc Validation <a name="ad-hoc-validation"></a>
Qiang Xue committed
241

Qiang Xue committed
242
Sometimes you need to do *ad hoc validation* for values that are not bound to any model.
243

Qiang Xue committed
244 245
If you only need to perform one type of validation (e.g. validating email addresses), you may call
the [[yii\validators\Validator::validate()|validate()]] method of the desired validator, like the following:
246 247 248 249

```php
$email = 'test@example.com';
$validator = new yii\validators\EmailValidator();
Qiang Xue committed
250

Qiang Xue committed
251
if ($validator->validate($email, $error)) {
252
    echo 'Email is valid.';
253
} else {
254
    echo $error;
255 256
}
```
Alexander Makarov committed
257

Qiang Xue committed
258 259
> Note: Not all validators support such kind of validation. An example is the [unique](tutorial-core-validators.md#unique)
  core validator which is designed to work with a model only.
Qiang Xue committed
260

Qiang Xue committed
261 262
If you need to perform multiple validations against several values, you can use [[yii\base\DynamicModel]]
which supports declaring both attributes and rules on the fly. Its usage is like the following:
Qiang Xue committed
263 264 265 266 267

```php
public function actionSearch($name, $email)
{
    $model = DynamicModel::validateData(compact('name', 'email'), [
Ryadnov Andrey committed
268
        [['name', 'email'], 'string', 'max' => 128],
Qiang Xue committed
269 270
        ['email', 'email'],
    ]);
Qiang Xue committed
271

Qiang Xue committed
272 273 274 275 276 277 278 279
    if ($model->hasErrors()) {
        // validation fails
    } else {
        // validation succeeds
    }
}
```

Qiang Xue committed
280 281 282 283 284
The [[yii\base\DynamicModel::validateData()]] method creates an instance of `DynamicModel`, defines the attributes
using the given data (`name` and `email` in this example), and then calls [[yii\base\Model::validate()]]
with the given rules.

Alternatively, you may use the following more "classic" syntax to perform ad hoc data validation:
Qiang Xue committed
285

Qiang Xue committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
```php
public function actionSearch($name, $email)
{
    $model = new DynamicModel(compact('name', 'email'));
    $model->addRule(['name', 'email'], 'string', ['max' => 128])
        ->addRule('email', 'email')
        ->validate();

    if ($model->hasErrors()) {
        // validation fails
    } else {
        // validation succeeds
    }
}
```

After validation, you can check if the validation succeeds or not by calling the
[[yii\base\DynamicModel::hasErrors()|hasErrors()]] method, and then get the validation errors from the
[[yii\base\DynamicModel::errors|errors]] property, like you do with a normal model.
Qiang Xue committed
305 306 307
You may also access the dynamic attributes defined through the model instance, e.g.,
`$model->name` and `$model->email`.

Qiang Xue committed
308 309 310 311 312 313 314 315 316 317 318

## Creating Validators <a name="creating-validators"></a>

Besides using the [core validators](tutorial-core-validators.md) included in the Yii releases, you may also
create your own validators. You may create inline validators or standalone validators.


### Inline Validators <a name="inline-validators"></a>

An inline validator is one defined in terms of a model method or an anonymous function. The signature of
the method/function is:
Qiang Xue committed
319 320

```php
Qiang Xue committed
321 322 323 324
/**
 * @param string $attribute the attribute currently being validated
 * @param array $params the additional name-value pairs given in the rule
 */
Kevin LEVRON committed
325
function ($attribute, $params)
Qiang Xue committed
326 327
```

Qiang Xue committed
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
If an attribute fails the validation, the method/function should call [[yii\base\Model::addError()]] to save
the error message in the model so that it can be retrieved back later to present to end users.

Below are some examples:

```php
use yii\base\Model;

class MyForm extends Model
{
    public $country;
    public $token;

    public function rules()
    {
        return [
            // an inline validator defined as the model method validateCountry()
            ['country', 'validateCountry'],

            // an inline validator defined as an anonymous function
            ['token', function ($attribute, $params) {
                if (!ctype_alnum($this->$attribute)) {
                    $this->addError($attribute, 'The token must contain letters or digits.');
                }
            }],
        ];
    }

Johnny Theill committed
356
    public function validateCountry($attribute, $params)
Qiang Xue committed
357 358 359 360 361 362 363 364
    {
        if (!in_array($this->$attribute, ['USA', 'Web'])) {
            $this->addError($attribute, 'The country must be either "USA" or "Web".');
        }
    }
}
```

Qiang Xue committed
365 366
> Note: By default, inline validators will not be applied if their associated attributes receive empty inputs
  or if they have already failed some validation rules. If you want to make sure a rule is always applied,
Kevin LEVRON committed
367 368 369
  you may configure the [[yii\validators\Validator::skipOnEmpty|skipOnEmpty]] and/or [[yii\validators\Validator::skipOnError|skipOnError]]
  properties to be false in the rule declarations. For example:
> ```php
Qiang Xue committed
370 371 372 373 374
[
    ['country', 'validateCountry', 'skipOnEmpty' => false, 'skipOnError' => false],
]
```

Qiang Xue committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

### Standalone Validators <a name="standalone-validators"></a>

A standalone validator is a class extending [[yii\validators\Validator]] or its child class. You may implement
its validation logic by overriding the [[yii\validators\Validator::validateAttribute()]] method. If an attribute
fails the validation, call [[yii\base\Model::addError()]] to save the error message in the model, like you do
with [inline validators](#inline-validators). For example,

```php
namespace app\components;

use yii\validators\Validator;

class CountryValidator extends Validator
{
    public function validateAttribute($model, $attribute)
    {
        if (!in_array($model->$attribute, ['USA', 'Web'])) {
            $this->addError($attribute, 'The country must be either "USA" or "Web".');
        }
    }
}
```

If you want your validator to support validating a value without a model, you should also override
[[yii\validators\Validator::validate()]]. You may also override [[yii\validators\Validator::validateValue()]]
instead of `validateAttribute()` and `validate()` because by default the latter two methods are implemented
by calling `validateValue()`.


405 406 407 408 409 410
## Client-Side Validation <a name="client-side-validation"></a>

Client-side validation based on JavaScript is desirable when end users provide inputs via HTML forms, because
it allows users to find out input errors faster and thus provides better user experience. You may use or implement
a validator that supports client-side validation *in addition to* server-side validation.

RichWeber committed
411
> Info: While client-side validation is desirable, it is not a must. Its main purpose is to provide users better
412 413 414 415 416 417 418 419 420
  experience. Like input data coming from end users, you should never trust client-side validation. For this reason,
  you should always perform server-side validation by calling [[yii\base\Model::validate()]], like
  described in the previous subsections.


### Using Client-Side Validation <a name="using-client-side-validation"></a>

Many [core validators](tutorial-core-validators.md) support client-side validation out-of-box. All you need to do
is just to use [[yii\widgets\ActiveForm]] to build your HTML forms. For example, `LoginForm` below declares two
Qiang Xue committed
421
rules: one uses the [required](tutorial-core-validators.md#required) core validator which is supported on both
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
client and server sides; the other uses the `validatePassword` inline validator which is only supported on the server
side.

```php
namespace app\models;

use yii\base\Model;
use app\models\User;

class LoginForm extends Model
{
    public $username;
    public $password;

    public function rules()
    {
        return [
            // username and password are both required
            [['username', 'password'], 'required'],

            // password is validated by validatePassword()
            ['password', 'validatePassword'],
        ];
    }

    public function validatePassword()
    {
        $user = User::findByUsername($this->username);

        if (!$user || !$user->validatePassword($this->password)) {
            $this->addError('password', 'Incorrect username or password.');
        }
    }
}
```

The HTML form built by the following code contains two input fields `username` and `password`.
If you submit the form without entering anything, you will find the error messages requiring you
to enter something appear right away without any communication with the server.

```php
<?php $form = yii\widgets\ActiveForm::begin(); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <?= Html::submitButton('Login') ?>
<?php yii\widgets\ActiveForm::end(); ?>
```

Behind the scene, [[yii\widgets\ActiveForm]] will read the validation rules declared in the model
and generate appropriate JavaScript code for validators that support client-side validation. When a user
changes the value of an input field or submit the form, the client-side validation JavaScript will be triggered.

Qiang Xue committed
474 475 476
If you want to turn off client-side validation completely, you may configure the
[[yii\widgets\ActiveForm::enableClientValidation]] property to be false. You may also turn off client-side
validation of individual input fields by configuring their [[yii\widgets\ActiveField::enableClientValidation]]
477 478 479 480 481 482 483 484 485 486 487 488 489
property to be false.


### Implementing Client-Side Validation <a name="implementing-client-side-validation"></a>

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.
RichWeber committed
490
- `deferred`: an array which deferred objects can be pushed into (explained in the next subsection).
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532

In the following example, we create a `StatusValidator` which validates if an input is a valid status input
against the existing status data. The validator supports both server side and client side validation.

```php
namespace app\components;

use yii\validators\Validator;
use app\models\Status;

class StatusValidator extends Validator
{
    public function init()
    {
        parent::init();
        $this->message = 'Invalid status input.';
    }

    public function validateAttribute($model, $attribute)
    {
        $value = $model->$attribute;
        if (!Status::find()->where(['id' => $value])->exists()) {
            $model->addError($attribute, $this->message);
        }
    }

    public function clientValidateAttribute($model, $attribute, $view)
    {
        $statuses = json_encode(Status::find()->select('id')->asArray()->column());
        $message = json_encode($this->message);
        return <<<JS
if (!$.inArray(value, $statuses)) {
    messages.push($message);
}
JS;
    }
}
```

> Tip: The above code is given mainly to demonstrate how to support client-side validation. In practice,
  you may use the [in](tutorial-core-validators.md#in) core validator to achieve the same goal. You may
  write the validation rule like the following:
Kevin LEVRON committed
533
> ```php
534 535 536 537
[
    ['status', 'in', 'range' => Status::find()->select('id')->asArray()->column()],
]
```
RichWeber committed
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640

### Deferred Validation <a name="deferred-validation"></a>

If you need to perform asynchronous client-side validation, you can create [Deferred objects](http://api.jquery.com/category/deferred-object/).
For example, to perform a custom AJAX validation, you can use the following code:

```php
public function clientValidateAttribute($model, $attribute, $view)
{
    return <<<JS
        deferred.push($.get("/check", {value: value}).done(function(data) {
            if ('' !== data) {
                messages.push(data);
            }
        }));
JS;
}
```

In the above, the `deferred` variable is provided by Yii, which is an array of Deferred objects. The `$.get()`
jQuery method creates a Deferred object which is pushed to the `deferred` array.

You can also explicitly create a Deferred object and call its `resolve()` method when the asynchronous callback
is hit. The following example shows how to validate the dimensions of an uploaded image file on the client side.

```php
public function clientValidateAttribute($model, $attribute, $view)
{
    return <<<JS
        var def = $.Deferred();
        var img = new Image();
        img.onload = function() {
            if (this.width > 150) {
                messages.push('Image too wide!!');
            }
            def.resolve();
        }
        var reader = new FileReader();
        reader.onloadend = function() {
            img.src = reader.result;
        }
        reader.readAsDataURL(file);

        deferred.push(def);
JS;
}
```

> Note: The `resolve()` method must be called after the attribute has been validated. Otherwise the main form
  validation will not complete.

For simplicity, the `deferred` array is equipped with a shortcut method `add()` which automatically creates a Deferred
object and add it to the `deferred` array. Using this method, you can simplify the above example as follows,

```php
public function clientValidateAttribute($model, $attribute, $view)
{
    return <<<JS
        deferred.add(function(def) {
            var img = new Image();
            img.onload = function() {
                if (this.width > 150) {
                    messages.push('Image too wide!!');
                }
                def.resolve();
            }
            var reader = new FileReader();
            reader.onloadend = function() {
                img.src = reader.result;
            }
            reader.readAsDataURL(file);
        });
JS;
}
```


### AJAX Validation <a name="ajax-validation"></a>

Some validations can only be done on the server side, because only the server has the necessary information.
For example, to validate if a username is unique or not, it is necessary to check the user table on the server side.
You can use AJAX-based validation in this case. It will trigger an AJAX request in the background to validate the
input while keeping the same user experience as the regular client-side validation.

To enable AJAX validation for the whole form, you have to set the
[[yii\widgets\ActiveForm::enableAjaxValidation]] property to be `true`. You may also turn it on or off
for individual input fields by configuring their [[yii\widgets\ActiveField::enableAjaxValidation]] property.

You also need to prepare the server so that it can handle the AJAX validation requests.
This can be achieved by a code snippet like the following in controller actions:

```php
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
    Yii::$app->response->format = Response::FORMAT_JSON;
    return ActiveForm::validate($model);
}
```

The above code will check whether the current request is an AJAX. If yes, it will respond to
this request by running the validation and returning the errors in JSON format.

> Info: You can also use [Deferred Validation](#deferred-validation) to perform AJAX validation.
  However, the AJAX validation feature described here is more systematic and requires less coding effort.