input-validation.md 15.7 KB

Validating Input

In the Models section, we have described how data validation works in general. In this section, we will mainly focus on describing core validators, how to define your own validators, and different ways of using validators.

Error Messages

Core Validators

Yii provides a set of commonly used validators, found primarily within the yii\validators namespace.

Instead of using lengthy validator class names, you may use aliases to specify the use of these core validators. For example, you can use the alias required to refer to the [[yii\validators\RequiredValidator]] class:

public function rules()
{
    return [
        [['email', 'password'], 'required'],
    ];
}

The [[yii\validators\Validator::builtInValidators]] property declares all supported validator aliases.

In the following, we will describe the main usage and properties of every core validator.

[[yii\validators\BooleanValidator|boolean]]

This validator checks if the input value is a boolean.

  • trueValue: the value representing true. Defaults to '1'.
  • falseValue: the value representing false. Defaults to '0'.
  • strict: whether the type of the input value should match that of trueValue and falseValue. Defaults to false.
[
    // checks if "selected" is either 0 or 1, regardless of data type
    ['selected', 'boolean'],

    // checks if "deleted" is of boolean type, either true or false
    ['deleted', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true],
]

Note: Because data input submitted via HTML forms are all strings, you normally should leave the [[yii\validators\BooleanValidator::strict|strict]] property as false.

[[yii\captcha\CaptchaValidator|captcha]]

This validator is usually used together with [[yii\captcha\CaptchaAction]] and [[yii\captcha\Captcha]] to make sure an input is the same as the verification code displayed by [[yii\captcha\Captcha|CAPTCHA]] widget.

  • caseSensitive: whether the comparison of the verification code is case sensitive. Defaults to false.
  • captchaAction: the route corresponding to the [[yii\captcha\CaptchaAction|CAPTCHA action]] that renders the CAPTCHA image. Defaults to 'site/captcha'.
  • skipOnEmpty: whether the validation can be skipped if the input is empty. Defaults to false, which means the input is required.
[
    ['verificationCode', 'captcha'],
]

[[yii\validators\CompareValidator|compare]]

This validator compares the specified input value with another one and make sure if their relationship is as specified by the operator property.

  • compareAttribute: the name of the attribute whose value should be compared with. When the validator is being used to validate an attribute, the default value of this property would be the name of the attribute suffixed with _repeat. For example, if the attribute being validated is password, then this property will default to password_repeat.
  • compareValue: a constant value that the input value should be compared with. When both of this property and compareAttribute are specified, this property will take precedence.
  • operator: the comparison operator. Defaults to ==, meaning checking if the input value is equal to that of compareAttribute or compareValue. The following operators are supported:
    • ==: check if two values are equal. The comparison is done is non-strict mode.
    • ===: check if two values are equal. The comparison is done is strict mode.
    • !=: check if two values are NOT equal. The comparison is done is non-strict mode.
    • !==: check if two values are NOT equal. The comparison is done is strict mode.
    • >: check if value being validated is greater than the value being compared with.
    • >=: check if value being validated is greater than or equal to the value being compared with.
    • <: check if value being validated is less than the value being compared with.
    • <=: check if value being validated is less than or equal to the value being compared with.
[
    // validates if the value of "password" attribute equals to that of "password_repeat"
    ['password', 'compare'],

    // validates if age is greater than or equal to 30
    ['age', 'compare', 'compareValue' => 30, 'operator' => '>='],
]

[[yii\validators\DateValidator|date]]

Verifies if the attribute represents a date, time, or datetime in a proper format.

  • format, the date format that the value being validated should follow according to PHP date_create_from_format. ('Y-m-d')
  • timestampAttribute, the name of the attribute that should receive the parsed result.

[[yii\validators\DefaultValueValidator|default]]

Sets the attribute to be the specified default value.

  • value, the default value to be assigned.

[[yii\validators\NumberValidator|double]]

Validates that the attribute value is a number, integer or decimal.

  • max, the upper limit of the number (inclusive). (null)
  • min, the lower limit of the number (inclusive). (null)

[[yii\validators\EmailValidator|email]]

Validates that the attribute value is a valid email address. By default, this validator checks if the attribute value is a syntactical valid email address, but the validator can be configured to check the address's domain for the address's existence.

  • allowName, whether to allow the name in the email address (e.g. John Smith <john.smith@example.com>). (false).
  • checkMX, whether to check the MX record for the email address. (false)
  • checkPort, whether to check port 25 for the email address. (false)
  • enableIDN, whether the validation process should take into account IDN (internationalized domain names). (false)

[[yii\validators\ExistValidator|exist]]

Validates that the attribute value exists in a table.

  • targetClass, the ActiveRecord class name or alias of the class that should be used to look for the attribute value being validated. (ActiveRecord class of the attribute being validated)
  • targetAttribute, the ActiveRecord attribute name that should be used to look for the attribute value being validated. (name of the attribute being validated)

[[yii\validators\FileValidator|file]]

Verifies if an attribute is receiving a valid uploaded file.

  • types, an array of file name extensions that are allowed to be uploaded. (any)
  • minSize, the minimum number of bytes required for the uploaded file.
  • maxSize, the maximum number of bytes allowed for the uploaded file.
  • maxFiles, the maximum number of files that the given attribute can hold. (1)

[[yii\validators\FilterValidator|filter]]

Converts the attribute value by sending it through a filter.

  • filter, a PHP callback that defines a filter.

Typically a callback is either the name of PHP function:

['password', 'filter', 'filter' => 'trim'],

Or an anonymous function:

['text', 'filter', 'filter' => function ($value) {
    // here we are removing all swear words from text
    return $newValue;
}],

[[yii\validators\ImageValidator|image]]

[[yii\validators\RangeValidator|in]]

Validates that the attribute value is among a list of values.

  • range, a list of valid values that the attribute value should be among (inclusive).
  • strict, whether the comparison should be strict (both the type and value must be the same). (false)
  • not, whether to invert the validation logic. (false)

[[yii\validators\NumberValidator|integer]]

Validates that the attribute value is an integer.

  • max, the upper limit of the number (inclusive). (null)
  • min, the lower limit of the number (inclusive). (null)

[[yii\validators\RegularExpressionValidator|match]]

Validates that the attribute value matches the specified pattern defined by a regular expression.

  • pattern, the regular expression to be matched.
  • not, whether to invert the validation logic. (false)

[[yii\validators\NumberValidator|number]]

Validates that the attribute value is a number.

  • max, the upper limit of the number (inclusive). (null)
  • min, the lower limit of the number (inclusive). (null)

[[yii\validators\RequiredValidator|required]]

Validates that the specified attribute does not have a null or empty value.

  • requiredValue, the desired value that the attribute must have. (any)
  • strict, whether the comparison between the attribute value and [[yii\validators\RequiredValidator::requiredValue|requiredValue]] must match both value and type. (false)

[[yii\validators\SafeValidator|safe]]

Serves as a dummy validator whose main purpose is to mark the attributes to be safe for massive assignment.

[[yii\validators\StringValidator|string]]

Validates that the attribute value is of certain length.

  • length, specifies the length limit of the value to be validated (inclusive). Can be exactly X, [min X], [min X, max Y].
  • max, the upper length limit (inclusive). If not set, it means no maximum length limit.
  • min, the lower length limit (inclusive). If not set, it means no minimum length limit.
  • encoding, the encoding of the string value to be validated. ([[yii\base\Application::charset]])

[[yii\validators\FilterValidator|trim]]

[[yii\validators\UniqueValidator|unique]]

Validates that the attribute value is unique in the corresponding database table.

  • targetClass, the ActiveRecord class name or alias of the class that should be used to look for the attribute value being validated. (ActiveRecord class of the attribute being validated)
  • targetAttribute, the ActiveRecord attribute name that should be used to look for the attribute value being validated. (name of the attribute being validated)

[[yii\validators\UrlValidator|url]]

Validates that the attribute value is a valid http or https URL.

  • validSchemes, an array of URI schemes that should be considered valid. ['http', 'https']
  • defaultScheme, the default URI scheme. If the input doesn't contain the scheme part, the default scheme will be prepended to it. (null)
  • enableIDN, whether the validation process should take into account IDN (internationalized domain names). (false)

Creating Validators

If none of the built in validators fit your needs, you can create your own validator by creating a method in you model class. This method will be wrapped by an [[yii\validators\InlineValidator|InlineValidator]] an be called upon validation. You will do the validation of the attribute and [[yii\base\Model::addError()|add errors]] to the model when validation fails.

The method has the following signature public function myValidator($attribute, $params) while you are free to choose the name.

Here is an example implementation of a validator validating the age of a user:

public function validateAge($attribute, $params)
{
    $value = $this->$attribute;
    if (strtotime($value) > strtotime('now - ' . $params['min'] . ' years')) {
        $this->addError($attribute, 'You must be at least ' . $params['min'] . ' years old to register for this service.');
    }
}

public function rules()
{
    return [
        // ...
        [['birthdate'], 'validateAge', 'params' => ['min' => '12']],
    ];
}

You may also set other properties of the [[yii\validators\InlineValidator|InlineValidator]] in the rules definition, for example the [[yii\validators\InlineValidator::$skipOnEmpty|skipOnEmpty]] property:

[['birthdate'], 'validateAge', 'params' => ['min' => '12'], 'skipOnEmpty' => false],

Inline Validators

Standalone Validators

Client-Side Validation

Conditional Validation

To validate attributes only when certain conditions apply, e.g. the validation of one field depends on the value of another field you can use [[yii\validators\Validator::when|the when property]] to define such conditions:

['state', 'required', 'when' => function($model) { return $model->country == Country::USA; }],
['stateOthers', 'required', 'when' => function($model) { return $model->country != Country::USA; }],
['mother', 'required', 'when' => function($model) { return $model->age < 18 && $model->married != true; }],

For better readability the conditions can also be written like this:

public function rules()
{
    $usa = function($model) { return $model->country == Country::USA; };
    $notUsa = function($model) { return $model->country != Country::USA; };
    $child = function($model) { return $model->age < 18 && $model->married != true; };
    return [
        ['state', 'required', 'when' => $usa],
        ['stateOthers', 'required', 'when' => $notUsa], // note that it is not possible to write !$usa
        ['mother', 'required', 'when' => $child],
    ];
}

When you need conditional validation logic on client-side (enableClientValidation is true), don't forget to add whenClient:

public function rules()
{
    $usa = [
        'server-side' => function($model) { return $model->country == Country::USA; },
        'client-side' => "function (attribute, value) {return $('#country').value == 'USA';}"
    ];

    return [
        ['state', 'required', 'when' => $usa['server-side'], 'whenClient' => $usa['client-side']],
    ];
}

This guide describes all of Yii's validators and their parameters.

Data Filtering

Ad Hoc Validation

Sometimes you need to validate a value that is not bound to any model, such as a standalone email address. The Validator class has a validateValue method that can help you in these scenarios. Not all validator classes have implemented this method, but the ones that have implemented validateValue can be used without a model. For example, to validate an email stored in a string, you can do the following:

$email = 'test@example.com';
$validator = new yii\validators\EmailValidator();
if ($validator->validate($email, $error)) {
    echo 'Email is valid.';
} else {
    echo $error;
}

DynamicModel is a model class primarily used to support ad hoc data validation.

The typical usage of DynamicModel is as follows,

public function actionSearch($name, $email)
{
    $model = DynamicModel::validateData(compact('name', 'email'), [
        [['name', 'email'], 'string', 'max' => 128]],
        ['email', 'email'],
    ]);
    if ($model->hasErrors()) {
        // validation fails
    } else {
        // validation succeeds
    }
}

The above example shows how to validate $name and $email with the help of DynamicModel. The [[validateData()]] method creates an instance of DynamicModel, defines the attributes using the given data (name and email in this example), and then calls [[Model::validate()]].

You can check the validation result by [[hasErrors()]], like you do with a normal model. You may also access the dynamic attributes defined through the model instance, e.g., $model->name and $model->email.

Alternatively, you may use the following more "classic" syntax to perform ad-hoc data validation:

$model = new DynamicModel(compact('name', 'email'));
$model->addRule(['name', 'email'], 'string', ['max' => 128])
    ->addRule('email', 'email')
    ->validate();

DynamicModel implements the above ad-hoc data validation feature by supporting the so-called "dynamic attributes". It basically allows an attribute to be defined dynamically through its constructor or [[defineAttribute()]].