From 0e3e2698d75fad4a272fcc9b072fa69ce5d8be30 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Wed, 9 Jan 2013 11:13:49 -0500 Subject: [PATCH] cleanup of AR --- framework/db/ActiveQuery.php | 24 ++++---- framework/db/ActiveRecord.php | 85 ++++++---------------------- framework/db/ActiveRelation.php | 13 ++++- tests/unit/framework/db/ActiveRecordTest.php | 23 +++----- 4 files changed, 48 insertions(+), 97 deletions(-) diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php index 54a0a25..813936b 100644 --- a/framework/db/ActiveQuery.php +++ b/framework/db/ActiveQuery.php @@ -181,7 +181,11 @@ class ActiveQuery extends Query public function scopes($names) { - $this->scopes = $names; + $this->scopes = func_get_args(); + if (isset($this->scopes[0]) && is_array($this->scopes[0])) { + // the parameter is given as an array + $this->scopes = $this->scopes[0]; + } return $this; } @@ -234,10 +238,10 @@ class ActiveQuery extends Query protected function normalizeRelations($model, $with) { $relations = array(); - foreach ($with as $name => $options) { + foreach ($with as $name => $callback) { if (is_integer($name)) { - $name = $options; - $options = array(); + $name = $callback; + $callback = null; } if (($pos = strpos($name, '.')) !== false) { // with sub-relations @@ -260,15 +264,9 @@ class ActiveQuery extends Query } if (isset($childName)) { - if (isset($relation->with[$childName])) { - $relation->with[$childName] = array_merge($relation->with, $options); - } else { - $relation->with[$childName] = $options; - } - } else { - foreach ($options as $p => $v) { - $relation->$p = $v; - } + $relation->with[$childName] = $callback; + } elseif ($callback !== null) { + call_user_func($callback, $relation); } } return $relations; diff --git a/framework/db/ActiveRecord.php b/framework/db/ActiveRecord.php index 5b8cfe4..5075fae 100644 --- a/framework/db/ActiveRecord.php +++ b/framework/db/ActiveRecord.php @@ -16,7 +16,6 @@ use yii\base\ModelEvent; use yii\db\Exception; use yii\db\Connection; use yii\db\TableSchema; -use yii\db\Query; use yii\db\Expression; use yii\util\StringHelper; @@ -79,39 +78,37 @@ abstract class ActiveRecord extends Model * ~~~ * // find all customers * $customers = Customer::find()->all(); - * // find a single customer whose primary key value is 10 - * $customer = Customer::find(10); - * // the above is equivalent to: - * Customer::find()->where(array('id' => 10))->one(); * // find all active customers and order them by their age: * $customers = Customer::find() * ->where(array('status' => 1)) * ->orderBy('age') * ->all(); - * // or alternatively: - * $customers = Customer::find(array( - * 'where' => array('status' => 1), - * 'orderBy' => 'age', - * ))->all(); + * // find a single customer whose primary key value is 10 + * $customer = Customer::find(10); + * // the above is equivalent to: + * $customer = Customer::find()->where(array('id' => 10))->one(); + * // find a single customer whose age is 30 and whose status is 1 + * $customer = Customer::find(array('age' => 30, 'status' => 1)); + * // the above is equivalent to: + * $customer = Customer::find()->where(array('age' => 30, 'status' => 1))->one(); * ~~~ * * @param mixed $q the query parameter. This can be one of the followings: * * - a scalar value (integer or string): query by a single primary key value and return the * corresponding record. - * - an array of name-value pairs: it will be used to configure the [[ActiveQuery]] object. + * - an array of name-value pairs: query by a set of column values and return a single record matching them. + * - null: return a new [[ActiveQuery]] object for further query purpose. * - * @return ActiveQuery|ActiveRecord|boolean the [[ActiveQuery]] instance for query purpose, or - * the ActiveRecord object when a scalar is passed to this method which is considered to be a - * primary key value (false will be returned if no record is found in this case.) + * @return ActiveQuery|ActiveRecord|null When `$q` is null, a new [[ActiveQuery]] instance + * is returned; when `$q` is a scalar or an array, an ActiveRecord object matching it will be + * returned, or null will be returned if no match is found. */ public static function find($q = null) { $query = static::createQuery(); if (is_array($q)) { - foreach ($q as $name => $value) { - $query->$name = $value; - } + return $query->where($q)->one(); } elseif ($q !== null) { // query by primary key $primaryKey = static::primaryKey(); @@ -145,35 +142,23 @@ abstract class ActiveRecord extends Model * // count the total number of customers * echo Customer::count()->value(); * // count the number of active customers: - * echo Customer::count(array( - * 'where' => array('status' => 1), - * ))->value(); - * // equivalent usage: * echo Customer::count() * ->where(array('status' => 1)) * ->value(); - * // customize the count option + * // customize the count expression * echo Customer::count('COUNT(DISTINCT age)')->value(); * ~~~ * - * @param array|string $q the query option. This can be one of the followings: - * - * - an array of name-value pairs: it will be used to configure the [[ActiveQuery]] object. - * - a string: the count expression, e.g. 'COUNT(DISTINCT age)'. + * @param string $q the count expression. If null, it means `COUNT(*)`. * * @return ActiveQuery the [[ActiveQuery]] instance */ public static function count($q = null) { $query = static::createQuery(); - if (is_array($q)) { - foreach ($q as $name => $value) { - $query->$name = $value; - } - } elseif ($q !== null) { + if ($q !== null) { $query->select = array($q); - } - if ($query->select === null) { + } elseif ($query->select === null) { $query->select = array('COUNT(*)'); } return $query; @@ -441,40 +426,6 @@ abstract class ActiveRecord extends Model } /** - * Returns the related record(s). - * This method will return the related record(s) of the current record. - * If the relation is HAS_ONE or BELONGS_TO, it will return a single object - * or null if the object does not exist. - * If the relation is HAS_MANY or MANY_MANY, it will return an array of objects - * or an empty array. - * @param ActiveRelation|string $relation the relation object or the name of the relation - * @param array|\Closure $params additional parameters that customize the query conditions as specified in the relation declaration. - * @return mixed the related object(s). - * @throws Exception if the relation is not specified in [[relations()]]. - */ - public function findByRelation($relation, $params = array()) - { - if (is_string($relation)) { - $md = $this->getMetaData(); - if (!isset($md->relations[$relation])) { - throw new Exception(get_class($this) . ' has no relation named "' . $relation . '".'); - } - $relation = $md->relations[$relation]; - } - $relation = clone $relation; - if ($params instanceof \Closure) { - $params($relation); - } else { - foreach ($params as $name => $value) { - $relation->$name = $value; - } - } - - $finder = new ActiveFinder($this->getDbConnection()); - return $finder->findWithRecord($this, $relation); - } - - /** * Returns the list of all attribute names of the model. * The default implementation will return all column names of the table associated with this AR class. * @return array list of attribute names. diff --git a/framework/db/ActiveRelation.php b/framework/db/ActiveRelation.php index 8bd92cd..c654f89 100644 --- a/framework/db/ActiveRelation.php +++ b/framework/db/ActiveRelation.php @@ -27,7 +27,7 @@ class ActiveRelation extends ActiveQuery { /** * @var boolean whether this relation should populate all query results into AR instances. - * If false, only the first row of the results will be taken. + * If false, only the first row of the results will be retrieved. */ public $multiple; /** @@ -41,11 +41,11 @@ class ActiveRelation extends ActiveQuery * must be the corresponding columns from the primary table. * Do not prefix or quote the column names as they will be done automatically by Yii. */ - public $link; + protected $link; /** * @var array|ActiveRelation */ - public $via; + protected $via; /** * @param string $relationName @@ -262,4 +262,11 @@ class ActiveRelation extends ActiveQuery $sql = $db->getQueryBuilder()->build($this); return $db->createCommand($sql, $this->params)->queryAll(); } + + public function link($model) + { + /** + * 1. Set models + */ + } } diff --git a/tests/unit/framework/db/ActiveRecordTest.php b/tests/unit/framework/db/ActiveRecordTest.php index dc47010..b918953 100644 --- a/tests/unit/framework/db/ActiveRecordTest.php +++ b/tests/unit/framework/db/ActiveRecordTest.php @@ -36,26 +36,23 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase $this->assertTrue($customer instanceof Customer); $this->assertEquals('user2', $customer->name); + // find by column values + $customer = Customer::find(array('id' => 2, 'name' => 'user2')); + $this->assertTrue($customer instanceof Customer); + $this->assertEquals('user2', $customer->name); + $customer = Customer::find(array('id' => 2, 'name' => 'user1')); + $this->assertNull($customer); + // find by attributes $customer = Customer::find()->where(array('name' => 'user2'))->one(); $this->assertTrue($customer instanceof Customer); $this->assertEquals(2, $customer->id); - // find by Query array - $query = array( - 'where' => 'id=:id', - 'params' => array(':id' => 2), - ); - $customer = Customer::find($query)->one(); - $this->assertTrue($customer instanceof Customer); - $this->assertEquals('user2', $customer->name); // find count $this->assertEquals(3, Customer::count()->value()); - $this->assertEquals(2, Customer::count(array( - 'where' => 'id=1 OR id=2', - ))->value()); $this->assertEquals(2, Customer::find()->select('COUNT(*)')->where('id=1 OR id=2')->value()); + $this->assertEquals(6, Customer::count('SUM(id)')->value()); // asArray $customer = Customer::find()->where('id=2')->asArray()->one(); @@ -94,9 +91,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase public function testScope() { - $customers = Customer::find(array( - 'scopes' => array('active'), - ))->all(); + $customers = Customer::find()->scopes('active')->all(); $this->assertEquals(2, count($customers)); $customers = Customer::find()->active()->all();