Alexander Makarov
12 years ago
2 changed files with 244 additions and 214 deletions
@ -0,0 +1,244 @@ |
|||||||
|
Model |
||||||
|
===== |
||||||
|
|
||||||
|
A model in Yii is intended for application data storage and has the following basic features: |
||||||
|
|
||||||
|
- attribute declaration: a model defines what is considered an attribute. |
||||||
|
- attribute labels: each attribute may be associated with a label for display purpose. |
||||||
|
- massive attribute assignment. |
||||||
|
- scenario-based validation. |
||||||
|
|
||||||
|
Models of [[\yii\base\Model]] class are typically used to hold data and corresponding validation rules of complex web forms. |
||||||
|
The class is also a base for more advanced models with additional functionality such as [Active Record](active-record.md). |
||||||
|
|
||||||
|
Attributes |
||||||
|
---------- |
||||||
|
|
||||||
|
Attributes store the actual data represented by a model and can |
||||||
|
be accessed like object member variables. For example, a `Post` model |
||||||
|
may contain a `title` attribute and a `content` attribute which may be |
||||||
|
accessed as follows: |
||||||
|
|
||||||
|
```php |
||||||
|
$post->title = 'Hello, world'; |
||||||
|
$post->content = 'Something interesting is happening'; |
||||||
|
echo $post->title; |
||||||
|
echo $post->content; |
||||||
|
``` |
||||||
|
|
||||||
|
Since model implements [ArrayAccess](http://php.net/manual/en/class.arrayaccess.php) interface you can use it |
||||||
|
as array: |
||||||
|
|
||||||
|
```php |
||||||
|
$post['title'] = 'Hello, world'; |
||||||
|
$post['content'] = 'Something interesting is happening'; |
||||||
|
echo $post['title']; |
||||||
|
echo $post['content']; |
||||||
|
``` |
||||||
|
|
||||||
|
Default model implementation has a strict rule that all its attributes should be explicitly declared as public and |
||||||
|
non-static class properties such as the following: |
||||||
|
|
||||||
|
```php |
||||||
|
// LoginForm has two attributes: username and password |
||||||
|
class LoginForm extends \yii\base\Model |
||||||
|
{ |
||||||
|
public $username; |
||||||
|
public $password; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
In order to change it you can override `attributes()` method that returns a list of model attributes. For example, |
||||||
|
[[\yii\db\ActiveRecord]] class implements attributes as DB table columns: |
||||||
|
|
||||||
|
```php |
||||||
|
// Post is associated with the tbl_post DB table. |
||||||
|
// Its attributes correspond to the columns in tbl_post |
||||||
|
class Post extends \yii\db\ActiveRecord |
||||||
|
{ |
||||||
|
public function table() |
||||||
|
{ |
||||||
|
return 'tbl_post'; |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Attribute labels |
||||||
|
|
||||||
|
Attribute labels are mainly used for display purpose. For example, given an attribute `firstName`, we can declare |
||||||
|
a label `First Name` which is more user-friendly and can be displayed to end users. |
||||||
|
|
||||||
|
By default an attribute label is generated using [[\yii\base\Model\generateAttributeLabel()]] but the better way is to |
||||||
|
specify it explicitly like the following: |
||||||
|
|
||||||
|
```php |
||||||
|
// LoginForm has two attributes: username and password |
||||||
|
class LoginForm extends \yii\base\Model |
||||||
|
{ |
||||||
|
public $username; |
||||||
|
public $password; |
||||||
|
|
||||||
|
public function attributeLabels() |
||||||
|
{ |
||||||
|
reuturn array( |
||||||
|
'usename' => 'Your name', |
||||||
|
'password' => 'Your password', |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Scenarios |
||||||
|
--------- |
||||||
|
|
||||||
|
A model may be used in different scenarios. For example, a `User` model may be used to collect user login inputs, |
||||||
|
and it may also be used for user registration purpose. For this reason, each model has a property named `scenario` |
||||||
|
which stores the name of the scenario that the model is currently being used in. As we will explain in the next |
||||||
|
few sections, the concept of scenario is mainly used in validation and massive attribute assignment. |
||||||
|
|
||||||
|
Associated with each scenario is a list of attributes that are *active* in that particular scenario. For example, |
||||||
|
in the `login` scenario, only the `username` and `password` attributes are active; while in the `register` scenario, |
||||||
|
additional attributes such as `email` are *active*. |
||||||
|
|
||||||
|
Possible scenarios should be listed in the `scenarios()` method which returns an array whose keys are the scenario |
||||||
|
names and whose values are the corresponding active attribute lists. Below is an example: |
||||||
|
|
||||||
|
```php |
||||||
|
class User extends \yii\db\ActiveRecord |
||||||
|
{ |
||||||
|
public function scenarios() |
||||||
|
{ |
||||||
|
return array( |
||||||
|
'login' => array('username', 'password'), |
||||||
|
'register' => array('username', 'email', 'password'), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Sometimes, we want to mark that an attribute is not safe for massive assignment (but we still want it to be validated). |
||||||
|
We may do so by prefixing an exclamation character to the attribute name when declaring it in `scenarios()`. For example, |
||||||
|
|
||||||
|
```php |
||||||
|
array('username', 'password', '!secret') |
||||||
|
``` |
||||||
|
|
||||||
|
Validation |
||||||
|
---------- |
||||||
|
|
||||||
|
When a model is used to collect user input data via its attributes, it usually needs to validate the affected attributes |
||||||
|
to make sure they satisfy certain requirements, such as an attribute cannot be empty, an attribute must contain letters |
||||||
|
only, etc. If errors are found in validation, they may be presented to the user to help him fix the errors. |
||||||
|
The following example shows how the validation is performed: |
||||||
|
|
||||||
|
```php |
||||||
|
$model = new LoginForm; |
||||||
|
$model->username = $_POST['username']; |
||||||
|
$model->password = $_POST['password']; |
||||||
|
if ($model->validate()) { |
||||||
|
// ...login the user... |
||||||
|
} else { |
||||||
|
$errors = $model->getErrors(); |
||||||
|
// ...display the errors to the end user... |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
The possible validation rules for a model should be listed in its `rules()` method. Each validation rule applies to one |
||||||
|
or several attributes and is effective in one or several scenarios. A rule can be specified using a validator object - an |
||||||
|
instance of a [[\yii\validators\Validator]] child class, or an array with the following format: |
||||||
|
|
||||||
|
```php |
||||||
|
array( |
||||||
|
'attribute1, attribute2, ...', |
||||||
|
'validator class or alias', |
||||||
|
// specifies in which scenario(s) this rule is active. |
||||||
|
// if not given, it means it is active in all scenarios |
||||||
|
'on' => 'scenario1, scenario2, ...', |
||||||
|
// the following name-value pairs will be used |
||||||
|
// to initialize the validator properties... |
||||||
|
'name1' => 'value1', |
||||||
|
'name2' => 'value2', |
||||||
|
.... |
||||||
|
) |
||||||
|
``` |
||||||
|
|
||||||
|
When `validate()` is called, the actual validation rules executed are determined using both of the following criteria: |
||||||
|
|
||||||
|
- the rules must be associated with at least one active attribute; |
||||||
|
- the rules must be active for the current scenario. |
||||||
|
|
||||||
|
|
||||||
|
### Active Attributes |
||||||
|
|
||||||
|
An attribute is *active* if it is subject to some validations in the current scenario. |
||||||
|
|
||||||
|
|
||||||
|
### Safe Attributes |
||||||
|
|
||||||
|
An attribute is *safe* if it can be massively assigned in the current scenario. |
||||||
|
|
||||||
|
|
||||||
|
Massive Attribute Retrieval and Assignment |
||||||
|
------------------------------------------ |
||||||
|
|
||||||
|
Attributes can be massively retrieved via the `attributes` property. |
||||||
|
The following code will return *all* attributes in the `$post` model |
||||||
|
as an array of name-value pairs. |
||||||
|
|
||||||
|
```php |
||||||
|
$attributes = $post->attributes; |
||||||
|
var_dump($attributes); |
||||||
|
``` |
||||||
|
|
||||||
|
Using the same `attributes` property you can massively assign data from associative array to model attributes: |
||||||
|
|
||||||
|
```php |
||||||
|
$attributes = array( |
||||||
|
'title' => 'Model attributes', |
||||||
|
'create_time' => time(), |
||||||
|
); |
||||||
|
$post->attributes = $attributes; |
||||||
|
``` |
||||||
|
|
||||||
|
In the code above we're assigning corresponding data to model fields named as array keys. The key difference from mass |
||||||
|
retrieval that always works for all attributes is that in order to be assigned an attribute should be **safe** else |
||||||
|
it will be ignored. |
||||||
|
|
||||||
|
Validation rules and mass assignment |
||||||
|
------------------------------------ |
||||||
|
|
||||||
|
In Yii2 unlike Yii 1.x validation rules are separated from mass assignment. Validation |
||||||
|
rules are described in `rules()` method of the model while what's safe for mass |
||||||
|
assignment is described in `scenarios` method: |
||||||
|
|
||||||
|
```php |
||||||
|
function rules() |
||||||
|
{ |
||||||
|
return array( |
||||||
|
// rule applied when corresponding field is "safe" |
||||||
|
array('username', 'length', 'min' => 2), |
||||||
|
array('first_name', 'length', 'min' => 2), |
||||||
|
array('password', 'required'), |
||||||
|
|
||||||
|
// rule applied when scenario is "signup" no matter if field is "safe" or not |
||||||
|
array('hashcode', 'check', 'on' => 'signup'), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function scenarios() |
||||||
|
{ |
||||||
|
return array( |
||||||
|
// on signup allow mass assignment of username |
||||||
|
'signup' => array('username', 'password'), |
||||||
|
'update' => array('username', 'first_name'), |
||||||
|
); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Note that everything is unsafe by default and you can't make field "safe" without specifying scenario. |
||||||
|
|
||||||
|
See also |
||||||
|
-------- |
||||||
|
|
||||||
|
- [Model validation reference](validation.md) |
||||||
|
- [[\yii\base\Model]] |
@ -1,214 +0,0 @@ |
|||||||
Model |
|
||||||
===== |
|
||||||
|
|
||||||
Attributes |
|
||||||
---------- |
|
||||||
|
|
||||||
Attributes store the actual data represented by a model and can |
|
||||||
be accessed like object member variables. For example, a `Post` model |
|
||||||
may contain a `title` attribute and a `content` attribute which may be |
|
||||||
accessed as follows: |
|
||||||
|
|
||||||
~~~php |
|
||||||
$post->title = 'Hello, world'; |
|
||||||
$post->content = 'Something interesting is happening'; |
|
||||||
echo $post->title; |
|
||||||
echo $post->content; |
|
||||||
~~~ |
|
||||||
|
|
||||||
A model should list all its available attributes in the `attributes()` method. |
|
||||||
|
|
||||||
Attributes may be implemented in various ways. The [[\yii\base\Model]] class |
|
||||||
implements attributes as public member variables of the class, while the |
|
||||||
[[\yii\db\ActiveRecord]] class implements them as DB table columns. For example, |
|
||||||
|
|
||||||
~~~php |
|
||||||
// LoginForm has two attributes: username and password |
|
||||||
class LoginForm extends \yii\base\Model |
|
||||||
{ |
|
||||||
public $username; |
|
||||||
public $password; |
|
||||||
} |
|
||||||
|
|
||||||
// Post is associated with the tbl_post DB table. |
|
||||||
// Its attributes correspond to the columns in tbl_post |
|
||||||
class Post extends \yii\db\ActiveRecord |
|
||||||
{ |
|
||||||
public function table() |
|
||||||
{ |
|
||||||
return 'tbl_post'; |
|
||||||
} |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
### Attribute Labels |
|
||||||
|
|
||||||
|
|
||||||
Scenarios |
|
||||||
--------- |
|
||||||
|
|
||||||
A model may be used in different scenarios. For example, a `User` model may be |
|
||||||
used to collect user login inputs, and it may also be used for user registration |
|
||||||
purpose. For this reason, each model has a property named `scenario` which stores |
|
||||||
the name of the scenario that the model is currently being used in. As we will explain |
|
||||||
in the next few sections, the concept of scenario is mainly used in validation and |
|
||||||
massive attribute assignment. |
|
||||||
|
|
||||||
Associated with each scenario is a list of attributes that are *active* in that |
|
||||||
particular scenario. For example, in the `login` scenario, only the `username` |
|
||||||
and `password` attributes are active; while in the `register` scenario, |
|
||||||
additional attributes such as `email` are *active*. |
|
||||||
|
|
||||||
Possible scenarios should be listed in the `scenarios()` method which returns an array |
|
||||||
whose keys are the scenario names and whose values are the corresponding |
|
||||||
active attribute lists. Below is an example: |
|
||||||
|
|
||||||
~~~php |
|
||||||
class User extends \yii\db\ActiveRecord |
|
||||||
{ |
|
||||||
public function table() |
|
||||||
{ |
|
||||||
return 'tbl_user'; |
|
||||||
} |
|
||||||
|
|
||||||
public function scenarios() |
|
||||||
{ |
|
||||||
return array( |
|
||||||
'login' => array('username', 'password'), |
|
||||||
'register' => array('username', 'email', 'password'), |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
Sometimes, we want to mark that an attribute is not safe for massive assignment |
|
||||||
(but we still want it to be validated). We may do so by prefixing an exclamation |
|
||||||
character to the attribute name when declaring it in `scenarios()`. For example, |
|
||||||
|
|
||||||
~~~php |
|
||||||
array('username', 'password', '!secret') |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
Validation |
|
||||||
---------- |
|
||||||
|
|
||||||
When a model is used to collect user input data via its attributes, |
|
||||||
it usually needs to validate the affected attributes to make sure they |
|
||||||
satisfy certain requirements, such as an attribute cannot be empty, |
|
||||||
an attribute must contain letters only, etc. If errors are found in |
|
||||||
validation, they may be presented to the user to help him fix the errors. |
|
||||||
The following example shows how the validation is performed: |
|
||||||
|
|
||||||
~~~php |
|
||||||
$model = new LoginForm; |
|
||||||
$model->username = $_POST['username']; |
|
||||||
$model->password = $_POST['password']; |
|
||||||
if ($model->validate()) { |
|
||||||
// ...login the user... |
|
||||||
} else { |
|
||||||
$errors = $model->getErrors(); |
|
||||||
// ...display the errors to the end user... |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
The possible validation rules for a model should be listed in its |
|
||||||
`rules()` method. Each validation rule applies to one or several attributes |
|
||||||
and is effective in one or several scenarios. A rule can be specified |
|
||||||
using a validator object - an instance of a [[\yii\validators\Validator]] |
|
||||||
child class, or an array with the following format: |
|
||||||
|
|
||||||
~~~php |
|
||||||
array( |
|
||||||
'attribute1, attribute2, ...', |
|
||||||
'validator class or alias', |
|
||||||
// specifies in which scenario(s) this rule is active. |
|
||||||
// if not given, it means it is active in all scenarios |
|
||||||
'on' => 'scenario1, scenario2, ...', |
|
||||||
// the following name-value pairs will be used |
|
||||||
// to initialize the validator properties... |
|
||||||
'name1' => 'value1', |
|
||||||
'name2' => 'value2', |
|
||||||
.... |
|
||||||
) |
|
||||||
~~~ |
|
||||||
|
|
||||||
When `validate()` is called, the actual validation rules executed are |
|
||||||
determined using both of the following criteria: |
|
||||||
|
|
||||||
* the rules must be associated with at least one active attribute; |
|
||||||
* the rules must be active for the current scenario. |
|
||||||
|
|
||||||
|
|
||||||
### Active Attributes |
|
||||||
|
|
||||||
An attribute is *active* if it is subject to some validations in the current scenario. |
|
||||||
|
|
||||||
|
|
||||||
### Safe Attributes |
|
||||||
|
|
||||||
An attribute is *safe* if it can be massively assigned in the current scenario. |
|
||||||
|
|
||||||
|
|
||||||
Massive Access of Attributes |
|
||||||
---------------------------- |
|
||||||
|
|
||||||
|
|
||||||
Massive Attribute Retrieval |
|
||||||
--------------------------- |
|
||||||
|
|
||||||
Attributes can be massively retrieved via the `attributes` property. |
|
||||||
The following code will return *all* attributes in the `$post` model |
|
||||||
as an array of name-value pairs. |
|
||||||
|
|
||||||
~~~php |
|
||||||
$attributes = $post->attributes; |
|
||||||
var_dump($attributes); |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
Massive Attribute Assignment |
|
||||||
---------------------------- |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Safe Attributes |
|
||||||
--------------- |
|
||||||
|
|
||||||
Safe attributes are those that can be massively assigned. For example, |
|
||||||
|
|
||||||
Validation rules and mass assignment |
|
||||||
------------------------------------ |
|
||||||
|
|
||||||
In Yii2 unlike Yii 1.x validation rules are separated from mass assignment. Validation |
|
||||||
rules are described in `rules()` method of the model while what's safe for mass |
|
||||||
assignment is described in `scenarios` method: |
|
||||||
|
|
||||||
```php |
|
||||||
|
|
||||||
function rules() { |
|
||||||
return array( |
|
||||||
// rule applied when corresponding field is "safe" |
|
||||||
array('username', 'length', 'min' => 2), |
|
||||||
array('first_name', 'length', 'min' => 2), |
|
||||||
array('password', 'required'), |
|
||||||
|
|
||||||
// rule applied when scenario is "signup" no matter if field is "safe" or not |
|
||||||
array('hashcode', 'check', 'on' => 'signup'), |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
function scenarios() { |
|
||||||
return array( |
|
||||||
// on signup allow mass assignment of username |
|
||||||
'signup' => array('username', 'password'), |
|
||||||
'update' => array('username', 'first_name'), |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
``` |
|
||||||
|
|
||||||
Note that everything is unsafe by default and you can't make field "safe" |
|
||||||
without specifying scenario. |
|
Loading…
Reference in new issue