From 9bc5868dd1f1d843c133d73726fd3f01197a3d5d Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 3 Jul 2013 02:18:27 +0400 Subject: [PATCH] model guide --- docs/guide/model.md | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++ docs/model.md | 214 --------------------------------------------- 2 files changed, 244 insertions(+), 214 deletions(-) delete mode 100644 docs/model.md diff --git a/docs/guide/model.md b/docs/guide/model.md index e69de29..a296fe8 100644 --- a/docs/guide/model.md +++ b/docs/guide/model.md @@ -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]] diff --git a/docs/model.md b/docs/model.md deleted file mode 100644 index 4c39a5b..0000000 --- a/docs/model.md +++ /dev/null @@ -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. \ No newline at end of file