Commit b51d3474 by Qiang Xue

Added count, average, sum, min, max, scalar methods to ActiveQuery.

Added support for scopes defined in AR classes.
parent 63bb6efb
No related merge requests found
...@@ -57,11 +57,10 @@ return array( ...@@ -57,11 +57,10 @@ return array(
### Getting Data from Database ### Getting Data from Database
There are three ActiveRecord methods for getting data: There are two ActiveRecord methods for getting data:
- [[find()]] - [[find()]]
- [[findBySql()]] - [[findBySql()]]
- [[count()]]
They all return an [[ActiveQuery]] instance. Coupled with the various customization and query methods They all return an [[ActiveQuery]] instance. Coupled with the various customization and query methods
provided by [[ActiveQuery]], ActiveRecord supports very flexible and powerful data retrieval approaches. provided by [[ActiveQuery]], ActiveRecord supports very flexible and powerful data retrieval approaches.
...@@ -88,9 +87,9 @@ $sql = 'SELECT * FROM tbl_customer'; ...@@ -88,9 +87,9 @@ $sql = 'SELECT * FROM tbl_customer';
$customers = Customer::findBySql($sql)->all(); $customers = Customer::findBySql($sql)->all();
// to return the number of *active* customers: // to return the number of *active* customers:
$count = Customer::count() $count = Customer::find()
->where(array('status' => $active)) ->where(array('status' => $active))
->value(); ->count();
// to return customers in terms of arrays rather than `Customer` objects: // to return customers in terms of arrays rather than `Customer` objects:
$customers = Customer::find()->asArray()->all(); $customers = Customer::find()->asArray()->all();
...@@ -222,10 +221,10 @@ subtotal exceeds certain amount: ...@@ -222,10 +221,10 @@ subtotal exceeds certain amount:
~~~ ~~~
class Customer extends \yii\db\ActiveRecord class Customer extends \yii\db\ActiveRecord
{ {
public function getBigOrders() public function getBigOrders($threshold = 100)
{ {
return $this->hasMany('Order', array('customer_id' => 'id')) return $this->hasMany('Order', array('customer_id' => 'id'))
->where('subtotal > 100') ->where('subtotal > :threshold', array(':threshold' => $threshold))
->orderBy('id'); ->orderBy('id');
} }
} }
......
...@@ -26,7 +26,12 @@ use yii\db\Exception; ...@@ -26,7 +26,12 @@ use yii\db\Exception;
* *
* - [[one()]]: returns a single record populated with the first row of data. * - [[one()]]: returns a single record populated with the first row of data.
* - [[all()]]: returns all records based on the query results. * - [[all()]]: returns all records based on the query results.
* - [[value()]]: returns the value of the first column in the first row of the query result. * - [[count()]]: returns the number of records.
* - [[sum()]]: returns the sum over the specified column.
* - [[average()]]: returns the average over the specified column.
* - [[min()]]: returns the min over the specified column.
* - [[max()]]: returns the max over the specified column.
* - [[scalar()]]: returns the value of the first column in the first row of the query result.
* - [[exists()]]: returns a value indicating whether the query result has data or not. * - [[exists()]]: returns a value indicating whether the query result has data or not.
* *
* Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]], * Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]],
...@@ -75,6 +80,24 @@ class ActiveQuery extends Query ...@@ -75,6 +80,24 @@ class ActiveQuery extends Query
/** /**
* PHP magic method.
* This method allows calling static method defined in [[modelClass]] via this query object.
* It is mainly implemented for supporting the feature of scope.
* @param string $name the method name to be called
* @param array $params the parameters passed to the method
* @return mixed the method return result
*/
public function __call($name, $params)
{
if (method_exists($this->modelClass, $name)) {
array_unshift($params, $this);
return call_user_func_array(array($this->modelClass, $name), $params);
} else {
return parent::__call($name, $params);
}
}
/**
* Executes query and returns all results as an array. * Executes query and returns all results as an array.
* @return array the query results. If the query results in nothing, an empty array will be returned. * @return array the query results. If the query results in nothing, an empty array will be returned.
*/ */
...@@ -119,12 +142,72 @@ class ActiveQuery extends Query ...@@ -119,12 +142,72 @@ class ActiveQuery extends Query
} }
/** /**
* Returns the number of records.
* @param string $q the COUNT expression. Defaults to '*'.
* Make sure you properly quote column names.
* @return integer number of records
*/
public function count($q = '*')
{
$this->select = array("COUNT($q)");
return $this->createCommand()->queryScalar();
}
/**
* Returns the sum of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names.
* @return integer the sum of the specified column values
*/
public function sum($q)
{
$this->select = array("SUM($q)");
return $this->createCommand()->queryScalar();
}
/**
* Returns the average of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names.
* @return integer the average of the specified column values.
*/
public function average($q)
{
$this->select = array("AVG($q)");
return $this->createCommand()->queryScalar();
}
/**
* Returns the minimum of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names.
* @return integer the minimum of the specified column values.
*/
public function min($q)
{
$this->select = array("MIN($q)");
return $this->createCommand()->queryScalar();
}
/**
* Returns the maximum of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names.
* @return integer the maximum of the specified column values.
*/
public function max($q)
{
$this->select = array("MAX($q)");
return $this->createCommand()->queryScalar();
}
/**
* Returns the query result as a scalar value. * Returns the query result as a scalar value.
* The value returned will be the first column in the first row of the query results. * The value returned will be the first column in the first row of the query results.
* @return string|boolean the value of the first column in the first row of the query result. * @return string|boolean the value of the first column in the first row of the query result.
* False is returned if the query result is empty. * False is returned if the query result is empty.
*/ */
public function value() public function scalar()
{ {
return $this->createCommand()->queryScalar(); return $this->createCommand()->queryScalar();
} }
...@@ -136,7 +219,7 @@ class ActiveQuery extends Query ...@@ -136,7 +219,7 @@ class ActiveQuery extends Query
public function exists() public function exists()
{ {
$this->select = array(new Expression('1')); $this->select = array(new Expression('1'));
return $this->value() !== false; return $this->scalar() !== false;
} }
/** /**
......
...@@ -128,36 +128,6 @@ class ActiveRecord extends Model ...@@ -128,36 +128,6 @@ class ActiveRecord extends Model
} }
/** /**
* Creates a `COUNT` query for this AR class.
*
* Below are some usage examples:
*
* ~~~
* // count the total number of customers
* echo Customer::count()->value();
* // count the number of active customers:
* echo Customer::count()
* ->where(array('status' => 1))
* ->value();
* // customize the count expression
* echo Customer::count('COUNT(DISTINCT age)')->value();
* ~~~
*
* @param string $q the count expression. If null, it means `COUNT(*)`.
* @return ActiveQuery the newly created [[ActiveQuery]] instance
*/
public static function count($q = null)
{
$query = static::createQuery();
if ($q !== null) {
$query->select = array($q);
} elseif ($query->select === null) {
$query->select = array('COUNT(*)');
}
return $query;
}
/**
* Updates the whole table using the provided attribute values and conditions. * Updates the whole table using the provided attribute values and conditions.
* For example, to change the status to be 1 for all customers whose status is 2: * For example, to change the status to be 1 for all customers whose status is 2:
* *
...@@ -646,7 +616,7 @@ class ActiveRecord extends Model ...@@ -646,7 +616,7 @@ class ActiveRecord extends Model
$values[$key] = isset($this->_attributes[$key]) ? $this->_attributes[$key] : null; $values[$key] = isset($this->_attributes[$key]) ? $this->_attributes[$key] : null;
} }
} }
$db = $this->getDbConnection(); $db = static::getDbConnection();
$command = $db->createCommand()->insert($this->tableName(), $values); $command = $db->createCommand()->insert($this->tableName(), $values);
if ($command->execute()) { if ($command->execute()) {
$table = $this->getTableSchema(); $table = $this->getTableSchema();
...@@ -1082,7 +1052,7 @@ class ActiveRecord extends Model ...@@ -1082,7 +1052,7 @@ class ActiveRecord extends Model
foreach ($extraColumns as $k => $v) { foreach ($extraColumns as $k => $v) {
$columns[$k] = $v; $columns[$k] = $v;
} }
$this->getDbConnection()->createCommand() static::getDbConnection()->createCommand()
->insert($viaTable, $columns)->execute(); ->insert($viaTable, $columns)->execute();
} else { } else {
$p1 = $model->isPrimaryKey(array_keys($relation->link)); $p1 = $model->isPrimaryKey(array_keys($relation->link));
...@@ -1153,7 +1123,7 @@ class ActiveRecord extends Model ...@@ -1153,7 +1123,7 @@ class ActiveRecord extends Model
foreach ($relation->link as $a => $b) { foreach ($relation->link as $a => $b) {
$columns[$b] = $model->$a; $columns[$b] = $model->$a;
} }
$command = $this->getDbConnection()->createCommand(); $command = static::getDbConnection()->createCommand();
if ($delete) { if ($delete) {
$command->delete($viaTable, $columns)->execute(); $command->delete($viaTable, $columns)->execute();
} else { } else {
......
...@@ -19,4 +19,9 @@ class Customer extends ActiveRecord ...@@ -19,4 +19,9 @@ class Customer extends ActiveRecord
{ {
return $this->hasMany('Order', array('customer_id' => 'id'))->orderBy('id'); return $this->hasMany('Order', array('customer_id' => 'id'))->orderBy('id');
} }
public static function active($query)
{
return $query->andWhere('status=1');
}
} }
\ No newline at end of file
...@@ -55,10 +55,17 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase ...@@ -55,10 +55,17 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertEquals(3, $customer->id); $this->assertEquals(3, $customer->id);
$this->assertEquals(4, $customer->status2); $this->assertEquals(4, $customer->status2);
// find count // find count, sum, average, min, max, scalar
$this->assertEquals(3, Customer::count()->value()); $this->assertEquals(3, Customer::find()->count());
$this->assertEquals(2, Customer::find()->select('COUNT(*)')->where('id=1 OR id=2')->value()); $this->assertEquals(2, Customer::find()->where('id=1 OR id=2')->count());
$this->assertEquals(6, Customer::count('SUM(id)')->value()); $this->assertEquals(6, Customer::find()->sum('id'));
$this->assertEquals(2, Customer::find()->average('id'));
$this->assertEquals(1, Customer::find()->min('id'));
$this->assertEquals(3, Customer::find()->max('id'));
$this->assertEquals(3, Customer::find()->select('COUNT(*)')->scalar());
// scope
$this->assertEquals(2, Customer::find()->active()->count());
// asArray // asArray
$customer = Customer::find()->where('id=2')->asArray()->one(); $customer = Customer::find()->where('id=2')->asArray()->one();
......
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