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
classCustomerextends\yii\db\ActiveRecord
classCustomerextends\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*FROMtbl_orderWHEREcustomer_id=1;
SELECT*FROMtbl_orderWHEREcustomer_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()]]
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
classUserextendsActiveRecord
classUserextendsActiveRecord
...
@@ -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