@@ -271,6 +271,12 @@ whose subtotal is greater than 100. To specify a different threshold value, use
$orders=$customer->getBigOrders(200)->all();
```
> Note: A relation method returns an instance of [[yii\db\ActiveRelation]]. If you access the relation like
an attribute, the return value will be the query result of the relation, which could be an instance of `ActiveRecord`,
an array of that, or null, depending the multiplicity of the relation. For example, `$customer->getOrders()` returns
an `ActiveRelation` instance, while `$customer->orders` returns an array of `Order` objects (or an empty array if
the query results in nothing).
Relations with Pivot Table
--------------------------
...
...
@@ -543,16 +549,19 @@ Finally when calling [[yii\db\ActiveRecord::delete()|delete()]] to delete an Act
3.[[yii\db\ActiveRecord::afterDelete()|afterDelete()]]: will trigger an [[yii\db\ActiveRecord::EVENT_AFTER_DELETE|EVENT_AFTER_DELETE]] event
Custom scopes
-------------
Scopes
------
When [[yii\db\ActiveRecord::find()|find()]] or [[yii\db\ActiveRecord::findBySql()|findBySql()]], it returns an [[yii\db\ActiveRecord::yii\db\ActiveQuery|yii\db\ActiveQuery]]
instance. You may call additional query methods, such as `where()`, `orderBy()`, to further specify the query conditions, etc.
When [[yii\db\ActiveRecord::find()|find()]] or [[yii\db\ActiveRecord::findBySql()|findBySql()]] Active Record method is being called without parameters it returns an [[yii\db\ActiveRecord::yii\db\ActiveQuery|yii\db\ActiveQuery]]
instance. This object holds all the parameters and conditions for a future query and also allows you to customize these
using a set of methods that are called scopes. By default there is a good set of such methods some of which we've
already used above: `where`, `orderBy`, `limit` etc.
It is possible that you may want to call the same set of query methods in different places. If this is the case,
you should consider defining the so-called *scopes*. A scope is essentially a method defined in a custom query class that
calls a set of query methods to modify the query object. You can then use a scope like calling a normal query method.
In many cases it is convenient to wrap extra conditions into custom scope methods. In order to do so you need two things.
First is creating a custom query class for your model. For example, a `Comment` may have a `CommentQuery`:
Two steps are required to define a scope. First create a custom query class for your model and define the needed scope
methods in this class. For example, create a `CommentQuery` class for the `Comment` model and define the `active()`
scope method like the following:
```php
namespaceapp\models;
...
...
@@ -575,7 +584,8 @@ Important points are:
2. A method should be `public` and should return `$this` in order to allow method chaining. It may accept parameters.
3. Check `ActiveQuery` methods that are very useful for modifying query conditions.
The second step is to use `CommentQuery` instead of regular `ActiveQuery` for `Comment` model:
Second, override `ActiveRecord::createQuery()` to use the custom query class instead of the regular `ActiveQuery`.
For the example above, you need to write the following code:
@@ -78,7 +78,7 @@ Yii tries to load appropriate translation from one of the message sources define
```
In the above `app*` is a pattern that specifies which categories are handled by the message source. In this case we're
handling everything that begins with `app`. You can also specify default translation, for more info see [this](specifying-default-translation) example.
handling everything that begins with `app`. You can also specify default translation, for more info see [this example](i18n.md#examples).
`class` defines which message source is used. The following message sources are available:
...
...
@@ -356,7 +356,8 @@ class Module extends \yii\base\Module
}
```
In the example above we are using wildcard for matching and then filtering each category per needed file.
In the example above we are using wildcard for matching and then filtering each category per needed file. Instead of using `fileMap` you can simply
use convention of category mapping to the same named file and use `Module::t('validation', 'your custom validation message')` or `Module::t('form', 'some form label')` directly.
###Translating widgets messages
...
...
@@ -405,6 +406,8 @@ class Menu extends Widget
}
```
Instead of using `fileMap` you can simply use convention of category mapping to the same named file and use `Menu::t('messages', 'new messages {messages}', ['{messages}' => 10])` directly.
> **Note**: For widgets you also can use i18n views, same rules as for controllers are applied to them too.
In keeping with the MVC approach, a model in Yii is intended for storing or temporarily representing application data. Yii models have the following basic features:
In keeping with the MVC approach, a model in Yii is intended for storing or temporarily representing application data.
Yii models have 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: the ability to populate multiple model attributes in one step.
- Scenario-based data validation.
Models in Yii extend from the [[\yii\base\Model]] class. Models are typically used to both hold data and define the validation rules for that data (aka, the business logic). The business logic greatly simplifies the generation of models from complex web forms by providing validation and error reporting.
The Model class is also the base class for more advanced models with additional functionality, such as [Active Record](active-record.md).
Models in Yii extend from the [[\yii\base\Model]] class. Models are typically used to both hold data and define
the validation rules for that data (aka, the business logic). The business logic greatly simplifies the generation
of models from complex web forms by providing validation and error reporting.
The Model class is also the base class for more advanced models with additional functionality, such
as [Active Record](active-record.md).
Attributes
----------
...
...
@@ -21,7 +26,7 @@ may contain a `title` attribute and a `content` attribute, accessible as follows
```php
$post=newPost;
$post->title='Hello, world';
$post->content='Something interesting is happening';
$post->content='Something interesting is happening.';
echo$post->title;
echo$post->content;
```
...
...
@@ -62,8 +67,11 @@ Attribute labels are mainly used for display purpose. For example, given an attr
a label `First Name` that is more user-friendly when displayed to end users in places such as form labels and
error messages. Given an attribute name, you can obtain its label by calling [[\yii\base\Model::getAttributeLabel()]].
To declare attribute labels, override the [[\yii\base\Model::attributeLabels()]] method. The overridden method returns a mapping of attribute names to attribute labels, as 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. In many cases, [[\yii\base\Model::generateAttributeLabel()]] will generate reasonable labels (e.g. `username` to `Username`, `orderNumber` to `Order Number`).
To declare attribute labels, override the [[\yii\base\Model::attributeLabels()]] method. The overridden method returns
a mapping of attribute names to attribute labels, as 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.
In many cases, [[\yii\base\Model::generateAttributeLabel()]] will generate reasonable labels (e.g. `username` to `Username`,
`orderNumber` to `Order Number`).
```php
// LoginForm has two attributes: username and password
...
...
@@ -86,7 +94,8 @@ Scenarios
---------
A model may be used in different *scenarios*. For example, a `User` model may be used to collect user login inputs,
but it may also be used for user registration purposes. In the one scenario, every piece of data is required; in the other, only the username and password would be.
but it may also be used for user registration purposes. In the one scenario, every piece of data is required;
in the other, only the username and password would be.
To easily implement the business logic for different scenarios, each model has a property named `scenario`
that stores the name of the scenario that the model is currently being used in. As will be explained in the next
...
...
@@ -112,6 +121,9 @@ class User extends \yii\db\ActiveRecord
}
```
If `scenarios` method is not defined, default scenario is applied. That means attributes with validation rules are
considered *active*.
If you want to keep the default scenario available besides your own scenarios, use inheritance to include it:
```php
classUserextends\yii\db\ActiveRecord
...
...
@@ -161,9 +173,9 @@ class EmployeeController extends \yii\web\Controller
```
The example above presumes that the model is based upon [Active Record](active-record.md). For basic form models,
scenarios are rarely needed, as the basic form model is normally tied directly to a single form.
The default implementation of the `scenarios()`-method will return all scenarios found in the `rules()`
declaration (explained in the next section) so in simple cases you do not need to define scenarios.
scenarios are rarely needed, as the basic form model is normally tied directly to a single form and, as noted above,
the default implementation of the `scenarios()` returns every property with active validation rule making it always
available for mass assignment and validation.
Validation
...
...
@@ -211,16 +223,6 @@ When `validate()` is called, the actual validation rules executed are determined
- the rule 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
------------------------------------------
...
...
@@ -229,18 +231,23 @@ 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);
$post=Post::find(42);
if($post){
$attributes=$post->attributes;
var_dump($attributes);
}
```
Using the same `attributes` property you can massively assign data from associative array to model attributes:
```php
$post=newPost();
$attributes=[
'title'=>'Model attributes',
'created_at'=>time(),
'title'=>'Massive assignment example',
'content'=>'Never allow assigning attributes that are not meant to be assigned.',
];
$post->attributes=$attributes;
var_dump($attributes);
```
In the code above we're assigning corresponding data to model attributes named as array keys. The key difference from mass
...
...
@@ -256,31 +263,151 @@ rules are described in `rules()` method of the model while what's safe for mass
assignment is described in `scenarios` method:
```php
functionrules()
classUserextendsActiveRecord
{
publicfunctionrules()
{
return[
// rule applied when corresponding field is "safe"
['username','string','length'=>[4,32]],
['first_name','string','max'=>128],
['password','required'],
// rule applied when scenario is "signup" no matter if field is "safe" or not
['hashcode','check','on'=>'signup'],
];
}
publicfunctionscenarios()
{
return[
// on signup allow mass assignment of username
'signup'=>['username','password'],
'update'=>['username','first_name'],
];
}
}
```
For the code above mass assignment will be allowed stsrictly according to `scenarios()`:
```php
$user=User::find(42);
$data=['password'=>'123'];
$user->attributes=$data;
print_r($data);
```
Will give you empty array because there's no default scenario defined in our `scenarios()`.
```php
$user=User::find(42);
$user->scenario='signup';
$data=[
'username'=>'samdark',
'password'=>'123',
'hashcode'=>'test',
];
$user->attributes=$data;
print_r($data);
```
Will give you the following:
```php
array(
'username'=>'samdark',
'first_name'=>null,
'password'=>'123',
'hashcode'=>null,// it's not defined in scenarios method
)
```
In case of not defined `scenarios` method like the following:
```php
classUserextendsActiveRecord
{
return[
// rule applied when corresponding field is "safe"
['username','string','length'=>[4,32]],
['first_name','string','max'=>128],
['password','required'],
// rule applied when scenario is "signup" no matter if field is "safe" or not
['hashcode','check','on'=>'signup'],
];
publicfunctionrules()
{
return[
['username','string','length'=>[4,32]],
['first_name','string','max'=>128],
['password','required'],
];
}
}
```
The code above assumes default scenario so mass assignment will be available for all fields with `rules` defined:
```php
$user=User::find(42);
$data=[
'username'=>'samdark',
'first_name'=>'Alexander',
'last_name'=>'Makarov',
'password'=>'123',
];
$user->attributes=$data;
print_r($data);
```
Will give you the following:
```php
array(
'username'=>'samdark',
'first_name'=>'Alexander',
'password'=>'123',
)
```
If you want some fields to be unsafe for default scenario:
- Bug #1265: AssetController does not override 'js' and 'css' for compressed bundles (klimov-paul)
- Bug #1326: The `visible` setting for `DetailView` doesn't work as expected (qiangxue)
- Bug #1412: `FileValidator` and `ImageValidator` still trigger `uploadRequired` error in some case when `skipOnEmpty` is true and no upload is provided (qiangxue)
- Bug #1446: Logging while logs are processed causes infinite loop (qiangxue)
- Bug #1497: Localized view files are not correctly returned (mintao)
- Bug #1500: Log messages exported to files are not separated by newlines (omnilight, qiangxue)
- Enh: Improved `QueryBuilder::buildLimit()` to support big numbers (qiangxue)
- Enh:#2211: Added typecast database types into php types (dizews)
- Enh #2240: Improved `yii\web\AssetManager::publish()`, `yii\web\AssetManager::getPublishedPath()` and `yii\web\AssetManager::getPublishedUrl()` to support aliases (vova07)
- Chg #1519: `yii\web\User::loginRequired()` now returns the `Response` object instead of exiting the application (qiangxue)
- Chg #1586: `QueryBuilder::buildLikeCondition()` will now escape special characters and use percentage characters by default (qiangxue)
...
...
@@ -139,6 +141,7 @@ Yii Framework 2 Change Log
- Chg #2173: Removed `StringHelper::diff()`, Moved `phpspec/php-diff` dependency from `yiisoft/yii2` to `yiisoft/yii2-gii` (samdark)
- Chg #2175: QueryBuilder will now append UNION statements at the end of the primary SQL (qiangxue)
- Chg #2210: Mysql driver will now treat `tinyint(1)` as integer instead of boolean (qiangxue)
- Chg #2248: Renamed `yii\base\Model::DEFAULT_SCENARIO` to `yii\base\Model::SCENARIO_DEFAULT` (samdark)
- Chg: Renamed `yii\jui\Widget::clientEventsMap` to `clientEventMap` (qiangxue)
- Chg: Renamed `ActiveRecord::getPopulatedRelations()` to `getRelatedRecords()` (qiangxue)
- Chg: Renamed `attributeName` and `className` to `targetAttribute` and `targetClass` for `UniqueValidator` and `ExistValidator` (qiangxue)
'No help for unknown command "{command}".'=>'Анықтама белгісіз команда үшін ақиық "{command}".',
'No help for unknown sub-command "{command}".'=>'Анықтама белгісіз субкоманда үшін ақиық "{command}".',
'No results found.'=>'Ештене табылган жок.',
'Only files with these extensions are allowed: {extensions}.'=>'Файлды жуктеу тек қана осы аумақтармен: {extensions}.',
'Only files with these mimeTypes are allowed: {mimeTypes}.'=>'Файлды жуктеу тек қана осы MIME-үлгілермен: {mimeTypes}.',
'No results found.'=>'Ештене табылған жок.',
'Only files with these extensions are allowed: {extensions}.'=>'Файлды жүктеу тек қана осы аумақтармен: {extensions}.',
'Only files with these mimeTypes are allowed: {mimeTypes}.'=>'Файлды жүктеу тек қана осы MIME-үлгілермен: {mimeTypes}.',
'Page not found.'=>'Парақ табылган жок.',
'Please fix the following errors:'=>'Мына қателерді түзеніз:',
'Please upload a file.'=>'Файлды жуктеу.',
'Please upload a file.'=>'Файлды жүктеу.',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.'=>'Жазбалар көрсетілген <b>{begin, number}-{end, number}</b> дан <b>{totalCount, number}</b>.',
'The file "{file}" is not an image.'=>'Файл «{file}» сурет емес.',
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.'=>'Файлдын «{file}» көлемі өте үлкен. Өлшемі осыдан аспау керек {limit, number} {limit, plural, one{байт} few{байта} many{байт} other{байта}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.'=>'Файлдын «{file}» көлемі өте кіші. Өлшемі осыдан астам болу керек {limit, number} {limit, plural, one{байт} few{байта} many{байт} other{байта}}.',
'The format of {attribute} is invalid.'=>'Форматын мағынасы дұрыс емес «{attribute}».',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте үлкен. Ұзындығы осыдан аспау керек {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте үлкен. Ені осыдан аспау керек {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте кіші. Ұзындығы осыдан астам болу керек {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте кіші. Ені осыдан астам болу керек {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.',
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.'=>'Файл «{file}» көлемі өте үлкен. Өлшемі осыдан аспау керек,неғұрлым {limit, number} {limit, plural, one{байт} few{байтар} many{байтар} other{байтар}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.'=>'Файл «{file}» көлемі өте кіші. Өлшемі осыдан астам болу керек,неғұрлым {limit, number} {limit, plural, one{байт} few{байтар} many{байтар} other{байтар}}.',
'The format of {attribute} is invalid.'=>'Форматың мағынасы дұрыс емес «{attribute}».',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте үлкен. Ұзындығы осыдан аспау керек,неғұрлым {limit, number} {limit, plural, one{пиксель} few{пиксельдер} many{пиксельдер} other{пиксельдер}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте үлкен. Ені осыдан аспау керек,неғұрлым {limit, number} {limit, plural, one{пиксель} few{пиксельдер} many{пиксельдер} other{пиксельдер}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте кіші. Ұзындығы осыдан астам болу керек,неғұрлым limit, number} {limit, plural, one{пиксель} few{пиксельдер} many{пиксельдер} other{пиксельдер}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.'=>'Файл «{file}» өте кіші. Ені осыдан астам болу керек,неғұрлым {limit, number} {limit, plural, one{пиксель} few{пиксельдер} many{пиксельдер} other{пиксельдер}}.',
'The verification code is incorrect.'=>'Тексеріс коды қате.',
'You are not allowed to perform this action.'=>'Сізге адал әрекет жасауға болмайды',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.'=>'Сіз осыдан жүктеуге астам {limit, number} {limit, plural, one{файла} few{файлов} many{файлов} other{файла}}.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.'=>'Сіз осыдан жүктеуге астам {limit, number} {limit, plural, one{файла} few{файлдар} many{файлдар} other{файлдар}}.',
'the input value'=>'кіргізілген мағыналар',
'{attribute} "{value}" has already been taken.'=>'{attribute} «{value}» Бұл бос емес.',
'{attribute} cannot be blank.'=>'Толтыруға қажет «{attribute}».',
...
...
@@ -75,7 +75,7 @@ return array (
'{attribute} must be no less than {min}.'=>'Мағына «{attribute}» көп болу керек {min}.',
'{attribute} must be repeated exactly.'=>'Мағына «{attribute}» дәлме-дәл қайталану керек.',
'{attribute} must not be equal to "{compareValue}".'=>'Мағына «{attribute}» тең болмау керек «{compareValue}».',
'{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.'=>'Мағына «{attribute}» минимум болу керек {min, number} {min, plural, one{рәміз} few{рәміздер} many{рәміздерді} other{рәміздер}}.',
'{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.'=>'Мағына «{attribute}» өте үлкен болау керек {max, number} {max, plural, one{рәміз} few{рәміздер} many{рәміздерді} other{рәміздер}}.',
'{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.'=>'Мағына «{attribute}» болу керек {length, number} {length, plural, one{рәміз} few{рәміздер} many{рәміздерді} other{рәміздер}}.',
'{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.'=>'Мағына «{attribute}» минимум болу керек {min, number} {min, plural, one{рәміз} few{рәміздер} many{рәміздер} other{рәміздер}}.',
'{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.'=>'Мағына «{attribute}» өте үлкен болу керек {max, number} {max, plural, one{рәміз} few{рәміздер} many{рәміздер} other{рәміздер}}.',
'{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.'=>'Мағынада «{attribute}» болу керек {length, number} {length, plural, one{рәміз} few{рәміздер} many{рәміздер} other{рәміздер}}.',