You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

270 lines
8.8 KiB

12 years ago
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.
12 years ago
- scenario-based data validation.
12 years ago
12 years ago
Models extending from [[\yii\base\Model]] class are typically used to hold data and corresponding validation rules of complex web forms.
12 years ago
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
12 years ago
$post = new Post;
12 years ago
$post->title = 'Hello, world';
$post->content = 'Something interesting is happening';
echo $post->title;
echo $post->content;
```
12 years ago
Since [[\yii\base\Model|Model]] implements the [ArrayAccess](http://php.net/manual/en/class.arrayaccess.php) interface,
you can also access the attributes like accessing array elements:
12 years ago
```php
12 years ago
$post = new Post;
12 years ago
$post['title'] = 'Hello, world';
$post['content'] = 'Something interesting is happening';
echo $post['title'];
echo $post['content'];
```
12 years ago
By default, [[\yii\base\Model|Model]] requires that attributes be declared as *public* and *non-static*
class member variables. In the following example, the `LoginForm` model class declares two attributes:
`username` and `password`.
12 years ago
```php
// LoginForm has two attributes: username and password
class LoginForm extends \yii\base\Model
{
public $username;
public $password;
}
```
12 years ago
Derived model classes may use different ways to declare attributes by overriding the [[\yii\base\Model::attributes()|attributes()]]
method. For example, [[\yii\db\ActiveRecord]] defines attributes as the column names of the database table
that is associated with the class.
12 years ago
12 years ago
Attribute Labels
12 years ago
----------------
12 years ago
Attribute labels are mainly used for display purpose. For example, given an attribute `firstName`, we can declare
12 years ago
a label `First Name` which is more user-friendly and can be displayed to end users in places such as form labels,
error messages. Given an attribute name, you can obtain its label by calling [[\yii\base\Model::getAttributeLabel()]].
12 years ago
12 years ago
To declare attribute labels, you should override the [[\yii\base\Model::attributeLabels()]] method and return
a mapping from attribute names to attribute labels, like shown in the example below. If an attribute is not found
in this mapping, its label will be generated using the [[\yii\base\Model::generateAttributeLabel()]] method, which
in many cases, will generate reasonable labels (e.g. `username` to `Username`, `orderNumber` to `Order Number`).
12 years ago
```php
// LoginForm has two attributes: username and password
class LoginForm extends \yii\base\Model
{
public $username;
public $password;
public function attributeLabels()
{
12 years ago
return array(
12 years ago
'username' => 'Your name',
12 years ago
'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
12 years ago
few sections, the concept of scenario is mainly used for data validation and massive attribute assignment.
12 years ago
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'),
);
}
}
```
12 years ago
Sometimes, we want to mark an attribute as not safe for massive assignment (but we still want it to be validated).
12 years ago
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')
```
Active model scenario could be set using one of the following ways:
```php
class EmployeeController extends \yii\web\Controller
{
public function actionCreate($id = null)
{
// first way
$employee = new Employee(array('scenario' => 'managementPanel'));
// second way
$employee = new Employee;
$employee->scenario = 'managementPanel';
// third way
$employee = Employee::find()->where('id = :id', array(':id' => $id))->one();
if ($employee !== null) {
$employee->setScenario('managementPanel');
}
}
}
```
In the example above we are using [Active Record](active-record.md). For basic form models it's rarely needed to
use scenarios since form model is typically used for a single form.
12 years ago
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()) {
12 years ago
// ... login the user ...
12 years ago
} else {
$errors = $model->getErrors();
12 years ago
// ... display the errors to the end user ...
12 years ago
}
```
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
12 years ago
// to initialize the validator properties
'property1' => 'value1',
'property2' => 'value2',
// ...
12 years ago
)
```
When `validate()` is called, the actual validation rules executed are determined using both of the following criteria:
12 years ago
- the rule must be associated with at least one active attribute;
- the rule must be active for the current scenario.
12 years ago
### 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;
```
12 years ago
In the code above we're assigning corresponding data to model attributes named as array keys. The key difference from mass
12 years ago
retrieval that always works for all attributes is that in order to be assigned an attribute should be **safe** else
it will be ignored.
12 years ago
12 years ago
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', 'string', 'length' => array(4, 32)),
array('first_name', 'string', 'max' => 128),
12 years ago
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.
12 years ago
12 years ago
See also
--------
- [Model validation reference](validation.md)
- [[\yii\base\Model]]