Commit d1e0a545 by Qiang Xue

guide WIP [skip ci]

parent 1ea6e76e
......@@ -35,8 +35,8 @@ Application Structure
* [Applications](structure-applications.md)
* [Application Components](structure-application-components.md)
* [Controllers](structure-controllers.md)
* [Views](structure-views.md)
* [Models](structure-models.md)
* [Views](structure-views.md)
* **TBD** [Filters](structure-filters.md)
* **TBD** [Widgets](structure-widgets.md)
* **TBD** [Modules](structure-modules.md)
......@@ -88,9 +88,9 @@ Getting Data from Users
-----------------------
* [Creating Forms](input-forms.md)
* [Input Validation](input-validation.md)
* **TBD** [Uploading Files](input-file-uploading.md)
* **TBD** [Inputs for Multiple Models](input-multiple-models.md)
* [Validating Input](input-validation.md)
* **TBD** [Uploading Files](input-file-upload.md)
* **TBD** [Getting Data for Multiple Models](input-multiple-models.md)
Displaying Data
......
Model validation reference
==========================
Validating Input
================
> Note: This section is under development.
In the [Models](structure-models.md#validation) 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.
As a model both represents data and defines the business rules to which that data must adhere, comprehending data validation is key to using Yii. In order to learn model validation basics, please refer to [Model, Validation subsection](model.md#Validation).
## Error Messages
### Creating your own validators (Inline validators)
## Core 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.
Yii provides a set of commonly used validators, found primarily within the `yii\validators` namespace.
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:
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:
```php
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']],
[['email', 'password'], 'required'],
];
}
```
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:
The [[yii\validators\Validator::builtInValidators]] property declares all supported validator aliases.
```php
[['birthdate'], 'validateAge', 'params' => ['min' => '12'], 'skipOnEmpty' => false],
```
In the following, we will describe the main usage and properties of every core validator.
### 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:
### [[yii\validators\BooleanValidator|boolean]] <a name="boolean"></a>
```php
['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:
```php
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],
];
}
```
This validator checks if the input value is a boolean.
When you need conditional validation logic on client-side (`enableClientValidation` is true), don't forget
to add `whenClient`:
- `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`.
```php
public function rules()
{
$usa = [
'server-side' => function($model) { return $model->country == Country::USA; },
'client-side' => "function (attribute, value) {return $('#country').value == 'USA';}"
];
[
// checks if "selected" is either 0 or 1, regardless of data type
['selected', 'boolean'],
return [
['state', 'required', 'when' => $usa['server-side'], 'whenClient' => $usa['client-side']],
];
}
// checks if "deleted" is of boolean type, either true or false
['deleted', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true],
]
```
This guide describes all of Yii's validators and their parameters.
Standard Yii validators
-----------------------
The standard Yii validators are defined in many Yii classes, found primarily within the `yii\validators` namespace. But you do not need to specify the full namespace for the standard Yii validators as Yii can recognize them from defined aliases.
Here's the list of all validators bundled with the Yii framework, including their most useful properties. The default value for each property is indicated in parentheses. Note that this does not present an exhaustive list of each validator's properties.
### `boolean`: [[yii\validators\BooleanValidator|BooleanValidator]]
> Note: Because data input submitted via HTML forms are all strings, you normally should leave the
[[yii\validators\BooleanValidator::strict|strict]] property as false.
Checks if the attribute value is a boolean value.
- `trueValue`, the value representing true status. _(1)_
- `falseValue`, the value representing false status. _(0)_
- `strict`, whether to also compare the type of the value and `trueValue`/`falseValue`. _(false)_
### [[yii\captcha\CaptchaValidator|captcha]] <a name="captcha"></a>
### `captcha`: [[yii\captcha\CaptchaValidator|CaptchaValidator]]
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.
Validates that the attribute value is the same as the verification code displayed in the CAPTCHA. Should be used together
with [[yii\captcha\CaptchaAction]].
- `caseSensitive`: whether the comparison of the verification code is case sensitive. Defaults to false.
- `captchaAction`: the [route](structure-controllers.md#routes) 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.
```php
[
['verificationCode', 'captcha'],
]
```
- `caseSensitive`, whether the comparison is case sensitive. _(false)_
- `captchaAction`, the route of the controller action that renders the CAPTCHA image. _('site/captcha')_
### `compare`: [[yii\validators\CompareValidator|CompareValidator]]
### [[yii\validators\CompareValidator|compare]] <a name="compare"></a>
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.
```php
[
// validates if the value of "password" attribute equals to that of "password_repeat"
['password', 'compare'],
Compares the specified attribute value with another value and validates if they are equal.
// validates if age is greater than or equal to 30
['age', 'compare', 'compareValue' => 30, 'operator' => '>='],
]
```
- `compareAttribute`, the name of the attribute to be compared with. _(currentAttributeName&#95;repeat)_
- `compareValue`, a constant value to be compared with.
- `operator`, the operator for the comparison. _('==')_
### `date`: [[yii\validators\DateValidator|DateValidator]]
### [[yii\validators\DateValidator|date]] <a name="date"></a>
Verifies if the attribute represents a date, time, or datetime in a proper format.
......@@ -128,20 +110,20 @@ Verifies if the attribute represents a date, time, or datetime in a proper forma
[PHP date_create_from_format](http://www.php.net/manual/en/datetime.createfromformat.php). _('Y-m-d')_
- `timestampAttribute`, the name of the attribute that should receive the parsed result.
### `default`: [[yii\validators\DefaultValueValidator|DefaultValueValidator]]
### [[yii\validators\DefaultValueValidator|default]] <a name="default"></a>
Sets the attribute to be the specified default value.
- `value`, the default value to be assigned.
### `double`: [[yii\validators\NumberValidator|NumberValidator]]
### [[yii\validators\NumberValidator|double]] <a name="double"></a>
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)_
### `email`: [[yii\validators\EmailValidator|EmailValidator]]
### [[yii\validators\EmailValidator|email]] <a name="email"></a>
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.
......@@ -150,7 +132,7 @@ Validates that the attribute value is a valid email address. By default, this va
- `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)_
### `exist`: [[yii\validators\ExistValidator|ExistValidator]]
### [[yii\validators\ExistValidator|exist]] <a name="exist"></a>
Validates that the attribute value exists in a table.
......@@ -159,7 +141,7 @@ Validates that the attribute value exists in a table.
- `targetAttribute`, the ActiveRecord attribute name that should be used to look for the attribute value being validated.
_(name of the attribute being validated)_
### `file`: [[yii\validators\FileValidator|FileValidator]]
### [[yii\validators\FileValidator|file]] <a name="file"></a>
Verifies if an attribute is receiving a valid uploaded file.
......@@ -168,7 +150,7 @@ Verifies if an attribute is receiving a valid 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)_
### `filter`: [[yii\validators\FilterValidator|FilterValidator]]
### [[yii\validators\FilterValidator|filter]] <a name="filter"></a>
Converts the attribute value by sending it through a filter.
......@@ -189,7 +171,9 @@ Or an anonymous function:
}],
```
### `in`: [[yii\validators\RangeValidator|RangeValidator]]
### [[yii\validators\ImageValidator|image]] <a name="image"></a>
### [[yii\validators\RangeValidator|in]] <a name="in"></a>
Validates that the attribute value is among a list of values.
......@@ -197,44 +181,29 @@ Validates that the attribute value is among a list of values.
- `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)_
### `inline`: [[yii\validators\InlineValidator|InlineValidator]]
Uses a custom function to validate the attribute. You need to define a public method in your
model class that will evaluate the validity of the attribute. For example, if an attribute
needs to be divisible by 10, in the rules you would define: `['attributeName', 'isDivisibleByTen']`.
Then, your own method could look like this:
```php
public function isDivisibleByTen($attribute) {
if (($this->$attribute % 10) != 0) {
$this->addError($attribute, 'cannot divide value by 10');
}
}
```
### `integer`: [[yii\validators\NumberValidator|NumberValidator]]
### [[yii\validators\NumberValidator|integer]] <a name="integer"></a>
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)_
### `match`: [[yii\validators\RegularExpressionValidator|RegularExpressionValidator]]
### [[yii\validators\RegularExpressionValidator|match]] <a name="match"></a>
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)_
### `number`: [[yii\validators\NumberValidator|NumberValidator]]
### [[yii\validators\NumberValidator|number]] <a name="number"></a>
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)_
### `required`: [[yii\validators\RequiredValidator|RequiredValidator]]
### [[yii\validators\RequiredValidator|required]] <a name="required"></a>
Validates that the specified attribute does not have a null or empty value.
......@@ -242,11 +211,11 @@ Validates that the specified attribute does not have a null or empty value.
- `strict`, whether the comparison between the attribute value and
[[yii\validators\RequiredValidator::requiredValue|requiredValue]] must match both value and type. _(false)_
### `safe`: [[yii\validators\SafeValidator|SafeValidator]]
### [[yii\validators\SafeValidator|safe]] <a name="safe"></a>
Serves as a dummy validator whose main purpose is to mark the attributes to be safe for massive assignment.
### `string`: [[yii\validators\StringValidator|StringValidator]]
### [[yii\validators\StringValidator|string]] <a name="string"></a>
Validates that the attribute value is of certain length.
......@@ -255,7 +224,9 @@ Validates that the attribute value is of certain length.
- `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]])_
### `unique`: [[yii\validators\UniqueValidator|UniqueValidator]]
### [[yii\validators\FilterValidator|trim]] <a name="trim"></a>
### [[yii\validators\UniqueValidator|unique]] <a name="unique"></a>
Validates that the attribute value is unique in the corresponding database table.
......@@ -264,7 +235,7 @@ Validates that the attribute value is unique in the corresponding database table
- `targetAttribute`, the ActiveRecord attribute name that should be used to look for the attribute value being validated.
_(name of the attribute being validated)_
### `url`: [[yii\validators\UrlValidator|UrlValidator]]
### [[yii\validators\UrlValidator|url]] <a name="url"></a>
Validates that the attribute value is a valid http or https URL.
......@@ -273,8 +244,102 @@ Validates that the attribute value is a valid http or https URL.
prepended to it. _(null)_
- `enableIDN`, whether the validation process should take into account IDN (internationalized domain names). _(false)_
Validating values out of model context
--------------------------------------
## 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:
```php
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:
```php
[['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:
```php
['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:
```php
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`:
```php
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:
......@@ -289,4 +354,42 @@ if ($validator->validate($email, $error)) {
}
```
TBD: refer to http://www.yiiframework.com/wiki/56/ for the format
DynamicModel is a model class primarily used to support ad hoc data validation.
The typical usage of DynamicModel is as follows,
```php
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:
```php
$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()]].
......@@ -218,7 +218,7 @@ should be displayed to help the user to fix the errors.
You may call [[yii\base\Model::validate()]] to trigger validation. The method will go through every *active rule*
and make sure it is satisfied. If not, an error message will be generated for each failed rule and attribute.
The method returns a boolean value indicating whether all rules are satisfied. If not, you may retrieve the
error messages through the property [[yii\base\Model::errors]]. For example,
error messages through the property [[yii\base\Model::errors]] or [[yii\base\Model::firstErrors]]. For example,
```php
$model = new \app\models\ContactForm;
......
......@@ -10,7 +10,7 @@ namespace yii\base;
use yii\validators\Validator;
/**
* DynamicModel is a model class primarily used to support ad-hoc data validation.
* DynamicModel is a model class primarily used to support ad hoc data validation.
*
* The typical usage of DynamicModel is as follows,
*
......
......@@ -12,7 +12,7 @@ use yii\base\InvalidConfigException;
use yii\helpers\Html;
/**
* CompareValidator compares the specified attribute value with another value and validates if they are equal.
* CompareValidator compares the specified attribute value with another value.
*
* The value being compared with can be another attribute value
* (specified via [[compareAttribute]]) or a constant (specified via
......@@ -47,14 +47,14 @@ class CompareValidator extends Validator
/**
* @var string the operator for comparison. The following operators are supported:
*
* - '==': validates to see if the two values are equal. The comparison is done is non-strict mode.
* - '===': validates to see if the two values are equal. The comparison is done is strict mode.
* - '!=': validates to see if the two values are NOT equal. The comparison is done is non-strict mode.
* - '!==': validates to see if the two values are NOT equal. The comparison is done is strict mode.
* - `>`: validates to see if the value being validated is greater than the value being compared with.
* - `>=`: validates to see if the value being validated is greater than or equal to the value being compared with.
* - `<`: validates to see if the value being validated is less than the value being compared with.
* - `<=`: validates to see if the value being validated is less than or equal to the value being compared with.
* - `==`: 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.
*/
public $operator = '==';
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment