@@ -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:
// todo: this tutorial may be merged into test-fixture.md
Fixtures are important part of testing. Their main purpose is to populate you with data that needed by testing
different cases. With this data using your tests becoming more efficient and useful.
Yii supports database fixtures via the `yii fixture` command line tool. This tool supports:
Yii supports fixtures via the `yii fixture` command line tool. This tool supports:
*Applying new fixtures to database tables;
*Clearing, database tables (with sequences);
*Loading fixtures to different storage such as: RDBMS, NoSQL, etc;
*Unloading fixtures in different ways (usually it is clearing storage);
* Auto-generating fixtures and populating it with random data.
Fixtures format
---------------
Fixtures are just plain php files returning array. These files are usually stored under `@tests/unit/fixtures` path, but it
can be [configured](#configure-command-globally) in other way. Example of fixture file:
Fixtures are objects with different methods and configurations, refer to official [documentation](https://github.com/yiisoft/yii2/blob/master/docs/guide/test-fixture.md) on them.
Lets assume we have fixtures data to load:
```
#users.php file under fixtures path
#users.php file under fixtures data path, by default @tests\unit\fixtures\data
return [
[
...
...
@@ -36,31 +38,35 @@ return [
],
];
```
This data will be loaded to the `users`, but before it will be loaded table `users` will be cleared: all data deleted, sequence reset.
If we are using fixture that loads data into database then these rows will be applied to `users` table. If we are using nosql fixtures, for example `mongodb`
fixture, then this data will be applied to `users` mongodb collection. In order to learn about implementing various loading strategies and more, refer to official [documentation](https://github.com/yiisoft/yii2/blob/master/docs/guide/test-fixture.md).
Above fixture example was auto-generated by `yii2-faker` extension, read more about it in these [section](#auto-generating-fixtures).
Fixture classes name should not be plural.
Loading fixtures
----------------
Applying fixtures
-----------------
Fixture classes should be suffixed by `Fixture` class. By default fixtures will be searched under `tests\unit\fixtures` namespace, you can
change this behavior with config or command options.
To apply fixture to the table, run the following command:
To apply fixture, run the following command:
```
yii fixture/apply <tbl_name>
yii fixture/apply <fixture_name>
```
The required `tbl_name` parameter specifies a database table to which data will be loaded. You can load data to several tables at once.
The required `fixture_name` parameter specifies a fixture name which data will be loaded. You can load several fixtures at once.
Below are correct formats of this command:
```
// apply fixtures to the "users" table of database
yii fixture/apply users
// apply `users` fixture
yii fixture/apply User
// same as above, because default action of "fixture" command is "apply"
yii fixture users
yii fixture User
// apply several fixtures to several tables. Note that there should not be any whitespace between ",", it should be one string.
yii fixture users,users_profiles
// apply several fixtures. Note that there should not be any whitespace between ",", it should be one string.
yii fixture User,UserProfile
// apply all fixtures
yii fixture/apply all
...
...
@@ -68,29 +74,31 @@ yii fixture/apply all
// same as above
yii fixture all
// apply fixtures to the table users, but fixtures will be taken from different path.
TBD, see also [Component.md](../api/base/Component.md).
There is no longer the need to define an `on`-method in order to define an event in Yii 2.0.
Instead, you can use whatever event names. To attach a handler to an event, you should
use the `on` method now:
[[ADD INTRODUCTION]]
Creating Event Handlers
-----------------------
In Yii 1, events were defined using the `onEventName` method syntax, such as `onBeforeSave`. This is no longer necessary in Yii 2, as event handling is now assigned using the `on` method. The method's first argument is the name of the event to watch for; the second is the handling method to be called when that event occurs:
```php
$component->on($eventName,$handler);
// To detach the handler, use:
```
[[LINK TO LIST OF EVENTS]]
The handler must be a valid PHP callback. This could be represented as:
* The name of a global function
* An array consisting of a model name and method name
* An array consisting of an object and a method name
As shown in the anonymous function example, the event handling function must be defined so that it takes one argument. This will be an [[Event]] object.
Removing Event Handlers
-----------------------
The correspondoing `off` method removes an event handler:
```php
// $component->off($eventName);
```
Yii supports the ability to associate multiple handlers with the same event. When using `off` as in the above, every handler is removed. To remove only a specific handler, provide that as the second argument to `off`:
```php
// $component->off($eventName, $handler);
```
The `$handler` should be presented in the `off` method in the same way as was presented in `on` in order to remove it.
Event Parameters
----------------
When you attach a handler, you can now associate it with some parameters which can be later
accessed via the event parameter by the handler:
You can make your event handlers easier to work with and more powerful by passing additional values as parameters.
```php
$component->on($eventName,$handler,$params);
```
The passed parameters will be available in the event handler through `$event->data`, which will be an array.
Because of this change, you can now use "global" events. Simply trigger and attach handlers to
an event of the application instance:
[[NEED TO CONFIRM THE ABOVE]]
Global Events
-------------
Thanks to the change in Yii 2 as to how event handlers are created, you can now use "global" events. To create a global event, simply attach handlers to an event on the application instance:
```php
Yii::$app->on($eventName,$handler);
....
// this will trigger the event and cause $handler to be invoked.
```
You can use the `trigger` method to trigger these events manually:
```php
// this will trigger the event and cause $handler to be invoked:
Yii::$app->trigger($eventName);
```
If you need to handle all instances of a class instead of the object you can attach a handler like the following:
Class Events
------------
You can also attach event handlers to all instances of a class instead of individual instances. To do so, use the static `Event::on` method:
@@ -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.
- Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder)
- Enh #1313: made index and type available in `ActiveRecord::instantiate()` to allow creating records based on elasticsearch type when doing cross index/type search (cebe)
- Enh #1382: Added a debug toolbar panel for elasticsearch (cebe)
- Enh #1765: Added support for primary key path mapping, pk can now be part of the attributes when mapping is defined (cebe)
- Chg #1765: Changed handling of ActiveRecord primary keys, removed getId(), use getPrimaryKey() instead (cebe)
- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe)
- 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,8 @@ 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 #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe)
- 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{рәміздер}}.',