Commit 505762d4 by Carsten Brandt

updated docs about active relation

parent cb8237c1
...@@ -21,7 +21,7 @@ $customer->save(); // a new row is inserted into tbl_customer ...@@ -21,7 +21,7 @@ $customer->save(); // a new row is inserted into tbl_customer
Declaring ActiveRecord Classes Declaring ActiveRecord Classes
------------------------------ ------------------------------
To declare an ActiveRecord class you need to extend [[\yii\db\ActiveRecord]] and To declare an ActiveRecord class you need to extend [[yii\db\ActiveRecord]] and
implement the `tableName` method: implement the `tableName` method:
```php ```php
...@@ -197,7 +197,7 @@ Customer::updateAllCounters(['age' => 1]); ...@@ -197,7 +197,7 @@ Customer::updateAllCounters(['age' => 1]);
Data Input and Validation Data Input and Validation
------------------------- -------------------------
ActiveRecord inherits data validation and data input features from [[\yii\base\Model]]. Data validation is called ActiveRecord inherits data validation and data input features from [[yii\base\Model]]. Data validation is called
automatically when `save()` is performed. If data validation fails, the saving operation will be cancelled. automatically when `save()` is performed. If data validation fails, the saving operation will be cancelled.
For more details refer to the [Model](model.md) section of this guide. For more details refer to the [Model](model.md) section of this guide.
...@@ -205,12 +205,15 @@ For more details refer to the [Model](model.md) section of this guide. ...@@ -205,12 +205,15 @@ For more details refer to the [Model](model.md) section of this guide.
Querying Relational Data Querying Relational Data
------------------------ ------------------------
You can use ActiveRecord to also query a table's relational data (i.e., selection of data from Table A can also pull in related data from Table B). Thanks to ActiveRecord, the relational data returned can be accessed like a property of the ActiveRecord object associated with the primary table. You can use ActiveRecord to also query a table's relational data (i.e., selection of data from Table A can also pull
in related data from Table B). Thanks to ActiveRecord, the relational data returned can be accessed like a property
of the ActiveRecord object associated with the primary table.
For example, with an appropriate relation declaration, by accessing `$customer->orders` you may obtain For example, with an appropriate relation declaration, by accessing `$customer->orders` you may obtain
an array of `Order` objects which represent the orders placed by the specified customer. an array of `Order` objects which represent the orders placed by the specified customer.
To declare a relation, define a getter method which returns an [[yii\db\ActiveRelation]] object. For example, To declare a relation, define a getter method which returns an [[yii\db\ActiveQuery]] object that has relation
information about the relation context and thus will only query for related records. For example,
```php ```php
class Customer extends \yii\db\ActiveRecord class Customer extends \yii\db\ActiveRecord
...@@ -235,7 +238,7 @@ class Order extends \yii\db\ActiveRecord ...@@ -235,7 +238,7 @@ class Order extends \yii\db\ActiveRecord
The methods [[yii\db\ActiveRecord::hasMany()]] and [[yii\db\ActiveRecord::hasOne()]] used in the above The methods [[yii\db\ActiveRecord::hasMany()]] and [[yii\db\ActiveRecord::hasOne()]] used in the above
are used to model the many-one relationship and one-one relationship in a relational database. are used to model the many-one relationship and one-one relationship in a relational database.
For example, a customer has many orders, and an order has one customer. For example, a customer has many orders, and an order has one customer.
Both methods take two parameters and return an [[yii\db\ActiveRelation]] object: Both methods take two parameters and return an [[yii\db\ActiveQuery]] object:
- `$class`: the name of the class of the related model(s). This should be a fully qualified class name. - `$class`: the name of the class of the related model(s). This should be a fully qualified class name.
- `$link`: the association between columns from the two tables. This should be given as an array. - `$link`: the association between columns from the two tables. This should be given as an array.
...@@ -259,8 +262,8 @@ SELECT * FROM tbl_customer WHERE id=1; ...@@ -259,8 +262,8 @@ SELECT * FROM tbl_customer WHERE id=1;
SELECT * FROM tbl_order WHERE customer_id=1; SELECT * FROM tbl_order WHERE customer_id=1;
``` ```
> Tip: If you access the expression `$customer->orders` again, will it perform the second SQL query again? > Tip: If you access the expression `$customer->orders` again, it will not perform the second SQL query again.
Nope. The SQL query is only performed the first time when this expression is accessed. Any further The SQL query is only performed the first time when this expression is accessed. Any further
accesses will only return the previously fetched results that are cached internally. If you want to re-query accesses will only return the previously fetched results that are cached internally. If you want to re-query
the relational data, simply unset the existing one first: `unset($customer->orders);`. the relational data, simply unset the existing one first: `unset($customer->orders);`.
...@@ -280,8 +283,8 @@ class Customer extends \yii\db\ActiveRecord ...@@ -280,8 +283,8 @@ class Customer extends \yii\db\ActiveRecord
} }
``` ```
Remember that `hasMany()` returns an [[yii\db\ActiveRelation]] object which extends from [[yii\db\ActiveQuery]] Remember that `hasMany()` returns an [[yii\db\ActiveQuery]] object which allows you to customize the query by
and thus supports the same set of querying methods as [[yii\db\ActiveQuery]]. calling the methods of [[yii\db\ActiveQuery]].
With the above declaration, if you access `$customer->bigOrders`, it will only return the orders With the above declaration, if you access `$customer->bigOrders`, it will only return the orders
whose subtotal is greater than 100. To specify a different threshold value, use the following code: whose subtotal is greater than 100. To specify a different threshold value, use the following code:
...@@ -290,20 +293,19 @@ whose subtotal is greater than 100. To specify a different threshold value, use ...@@ -290,20 +293,19 @@ whose subtotal is greater than 100. To specify a different threshold value, use
$orders = $customer->getBigOrders(200)->all(); $orders = $customer->getBigOrders(200)->all();
``` ```
> Note: A relation method returns an instance of [[yii\db\ActiveRelation]]. If you access the relation like > Note: A relation method returns an instance of [[yii\db\ActiveQuery]]. 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 attribute (i.e. a class property), the return value will be the query result of the relation, which could be an instance of [[yii\db\ActiveRecord]],
an array of that, or null, depending the multiplicity of the relation. For example, `$customer->getOrders()` returns 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 an `ActiveQuery` instance, while `$customer->orders` returns an array of `Order` objects (or an empty array if
the query results in nothing). the query results in nothing).
Relations with Pivot Table Relations with Pivot Table
-------------------------- --------------------------
Sometimes, two tables are related together via an intermediary table called Sometimes, two tables are related together via an intermediary table called [pivot table][]. To declare such relations,
[pivot table](http://en.wikipedia.org/wiki/Pivot_table). To declare such relations, we can customize we can customize the [[yii\db\ActiveQuery]] object by calling its [[yii\db\ActiveQuery::via()|via()]] or
the [[yii\db\ActiveRelation]] object by calling its [[yii\db\ActiveRelation::via()]] or [[yii\db\ActiveRelation::viaTable()]] [[yii\db\ActiveQuery::viaTable()|viaTable()]] method.
method.
For example, if table `tbl_order` and table `tbl_item` are related via pivot table `tbl_order_item`, For example, if table `tbl_order` and table `tbl_item` are related via pivot table `tbl_order_item`,
we can declare the `items` relation in the `Order` class like the following: we can declare the `items` relation in the `Order` class like the following:
...@@ -319,8 +321,8 @@ class Order extends \yii\db\ActiveRecord ...@@ -319,8 +321,8 @@ class Order extends \yii\db\ActiveRecord
} }
``` ```
[[yii\db\ActiveRelation::via()]] method is similar to [[yii\db\ActiveRelation::viaTable()]] except that The [[yii\db\ActiveQuery::via()|via()]] method is similar to [[yii\db\ActiveQuery::viaTable()|viaTable()]] except that
the first parameter of [[yii\db\ActiveRelation::via()]] takes a relation name declared in the ActiveRecord class the first parameter of [[yii\db\ActiveQuery::via()|via()]] takes a relation name declared in the ActiveRecord class
instead of the pivot table name. For example, the above `items` relation can be equivalently declared as follows: instead of the pivot table name. For example, the above `items` relation can be equivalently declared as follows:
```php ```php
...@@ -339,6 +341,8 @@ class Order extends \yii\db\ActiveRecord ...@@ -339,6 +341,8 @@ class Order extends \yii\db\ActiveRecord
} }
``` ```
[pivot table]: http://en.wikipedia.org/wiki/Pivot_table "Pivot table on Wikipedia"
Lazy and Eager Loading Lazy and Eager Loading
---------------------- ----------------------
...@@ -457,7 +461,7 @@ if ($customer->orders[0]->customer === $customer) { ...@@ -457,7 +461,7 @@ if ($customer->orders[0]->customer === $customer) {
``` ```
To avoid the redundant execution of the last SQL statement, we could declare the inverse relations for the `customer` To avoid the redundant execution of the last SQL statement, we could declare the inverse relations for the `customer`
and the `orders` relations by calling the `inverseOf()` method, like the following: and the `orders` relations by calling the [[yii\db\ActiveQuery::inverseOf()|inverseOf()]] method, like the following:
```php ```php
class Customer extends ActiveRecord class Customer extends ActiveRecord
...@@ -500,7 +504,8 @@ if ($customers[0]->orders[0]->customer === $customers[0]) { ...@@ -500,7 +504,8 @@ if ($customers[0]->orders[0]->customer === $customers[0]) {
``` ```
> Note: Inverse relation cannot be defined with a relation that involves pivoting tables. > Note: Inverse relation cannot be defined with a relation that involves pivoting tables.
> That is, if your relation is defined with `via()` or `viaTable()`, you cannot call `inverseOf()` further. > That is, if your relation is defined with [[yii\db\ActiveQuery::via()|via()]] or [[yii\db\ActiveQuery::viaTable()|viaTable()]],
> you cannot call [[yii\db\ActiveQuery::inverseOf()]] further.
Joining with Relations Joining with Relations
...@@ -571,7 +576,7 @@ $orders = Order::find()->joinWith('books', false, 'INNER JOIN')->all(); ...@@ -571,7 +576,7 @@ $orders = Order::find()->joinWith('books', false, 'INNER JOIN')->all();
``` ```
Sometimes when joining two tables, you may need to specify some extra condition in the ON part of the JOIN query. Sometimes when joining two tables, you may need to specify some extra condition in the ON part of the JOIN query.
This can be done by calling the [[\yii\db\ActiveRelation::onCondition()]] method like the following: This can be done by calling the [[yii\db\ActiveQuery::onCondition()]] method like the following:
```php ```php
class User extends ActiveRecord class User extends ActiveRecord
...@@ -583,7 +588,8 @@ class User extends ActiveRecord ...@@ -583,7 +588,8 @@ class User extends ActiveRecord
} }
``` ```
In the above, the `hasMany()` method returns an `ActiveRelation` instance, upon which `onCondition()` is called In the above, the [[yii\db\ActiveRecord::hasMany()|hasMany()]] method returns an [[yii\db\ActiveQuery]] instance,
upon which [[yii\db\ActiveQuery::onCondition()|onCondition()]] is called
to specify that only items whose `category_id` is 1 should be returned. to specify that only items whose `category_id` is 1 should be returned.
When you perform query using [[yii\db\ActiveQuery::joinWith()|joinWith()]], the on-condition will be put in the ON part When you perform query using [[yii\db\ActiveQuery::joinWith()|joinWith()]], the on-condition will be put in the ON part
...@@ -665,8 +671,10 @@ Finally when calling [[yii\db\ActiveRecord::delete()|delete()]] to delete an Act ...@@ -665,8 +671,10 @@ Finally when calling [[yii\db\ActiveRecord::delete()|delete()]] to delete an Act
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]] When you call [[yii\db\ActiveRecord::find()|find()]] or [[yii\db\ActiveRecord::findBySql()|findBySql()]], it returns an
instance. You may call additional query methods, such as `where()`, `orderBy()`, to further specify the query conditions, etc. [[yii\db\ActiveQuery|ActiveQuery]] instance.
You may call additional query methods, such as [[yii\db\ActiveQuery::where()|where()]], [[yii\db\ActiveQuery::orderBy()|orderBy()]],
to further specify the query conditions.
It is possible that you may want to call the same set of query methods in different places. If this is the case, 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 you should consider defining the so-called *scopes*. A scope is essentially a method defined in a custom query class that
...@@ -933,4 +941,4 @@ See also ...@@ -933,4 +941,4 @@ See also
-------- --------
- [Model](model.md) - [Model](model.md)
- [[\yii\db\ActiveRecord]] - [[yii\db\ActiveRecord]]
...@@ -157,7 +157,7 @@ class ActiveRecord extends BaseActiveRecord ...@@ -157,7 +157,7 @@ class ActiveRecord extends BaseActiveRecord
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/ */
public static function createQuery($config = []) public static function createQuery($config = [])
......
...@@ -111,7 +111,7 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -111,7 +111,7 @@ abstract class ActiveRecord extends BaseActiveRecord
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/ */
public static function createQuery($config = []) public static function createQuery($config = [])
......
...@@ -64,7 +64,7 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord ...@@ -64,7 +64,7 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/ */
public static function createQuery($config = []) public static function createQuery($config = [])
......
...@@ -68,7 +68,7 @@ class ActiveRecord extends BaseActiveRecord ...@@ -68,7 +68,7 @@ class ActiveRecord extends BaseActiveRecord
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/ */
public static function createQuery($config = []) public static function createQuery($config = [])
......
...@@ -197,7 +197,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface ...@@ -197,7 +197,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
$this->filterByModels($viaModels); $this->filterByModels($viaModels);
} elseif (is_array($this->via)) { } elseif (is_array($this->via)) {
// via relation // via relation
/** @var ActiveRelation $viaQuery */ /** @var ActiveQuery $viaQuery */
list($viaName, $viaQuery) = $this->via; list($viaName, $viaQuery) = $this->via;
if ($viaQuery->multiple) { if ($viaQuery->multiple) {
$viaModels = $viaQuery->all(); $viaModels = $viaQuery->all();
......
...@@ -152,7 +152,7 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -152,7 +152,7 @@ abstract class ActiveRecord extends BaseActiveRecord
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/ */
public static function createQuery($config = []) public static function createQuery($config = [])
......
...@@ -168,7 +168,7 @@ class ActiveRecord extends BaseActiveRecord ...@@ -168,7 +168,7 @@ class ActiveRecord extends BaseActiveRecord
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/ */
public static function createQuery($config = []) public static function createQuery($config = [])
......
...@@ -131,7 +131,7 @@ interface ActiveRecordInterface ...@@ -131,7 +131,7 @@ interface ActiveRecordInterface
* Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the * Note that all queries should use [[Query::andWhere()]] and [[Query::orWhere()]] to keep the
* default condition. Using [[Query::where()]] will override the default condition. * default condition. Using [[Query::where()]] will override the default condition.
* *
* @param array $config the configuration passed to the ActiveRelation class. * @param array $config the configuration passed to the ActiveQuery class.
* @return ActiveQueryInterface the newly created [[ActiveQueryInterface|ActiveQuery]] instance. * @return ActiveQueryInterface the newly created [[ActiveQueryInterface|ActiveQuery]] instance.
*/ */
public static function createQuery($config = []); public static function createQuery($config = []);
......
...@@ -492,7 +492,7 @@ trait ActiveRecordTestTrait ...@@ -492,7 +492,7 @@ trait ActiveRecordTestTrait
} }
/** /**
* Ensure ActiveRelation does preserve order of items on find via() * Ensure ActiveRelationTrait does preserve order of items on find via()
* https://github.com/yiisoft/yii2/issues/1310 * https://github.com/yiisoft/yii2/issues/1310
*/ */
public function testFindEagerViaRelationPreserveOrder() public function testFindEagerViaRelationPreserveOrder()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment