Browse Source

Implemented new scope declaration syntax.

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
8c26893992
  1. 11
      framework/db/ar/ActiveFinder.php
  2. 8
      framework/db/ar/ActiveQuery.php
  3. 6
      framework/db/ar/ActiveRecord.php
  4. 9
      tests/unit/data/ar/Customer.php
  5. 21
      tests/unit/framework/db/ar/ActiveRecordTest.php

11
framework/db/ar/ActiveFinder.php

@ -196,6 +196,7 @@ class ActiveFinder extends \yii\base\Object
$records[$row[$query->index]] = $row; $records[$row[$query->index]] = $row;
} }
} else { } else {
/** @var $class ActiveRecord */
$class = $query->modelClass; $class = $query->modelClass;
if ($query->index === null) { if ($query->index === null) {
foreach ($rows as $row) { foreach ($rows as $row) {
@ -212,18 +213,20 @@ class ActiveFinder extends \yii\base\Object
protected function applyScopes($query) protected function applyScopes($query)
{ {
/** @var $class ActiveRecord */
$class = $query->modelClass; $class = $query->modelClass;
$class::defaultScope($query); $class::defaultScope($query);
if (is_array($query->scopes)) { if (is_array($query->scopes)) {
$scopes = $class::scopes(); $model = new $class;
foreach ($query->scopes as $name => $params) { foreach ($query->scopes as $name => $params) {
if (is_integer($name)) { if (is_string($params)) {
// scope name only without parameters
$name = $params; $name = $params;
$params = array(); $params = array();
} }
if (isset($scopes[$name])) { if (method_exists($class, $name)) {
array_unshift($params, $query); array_unshift($params, $query);
call_user_func_array($scopes[$name], $params); call_user_func_array(array($model, $name), $params);
} else { } else {
throw new Exception("$class has no scope named '$name'."); throw new Exception("$class has no scope named '$name'.");
} }

8
framework/db/ar/ActiveQuery.php

@ -46,11 +46,9 @@ class ActiveQuery extends BaseActiveQuery implements \IteratorAggregate, \ArrayA
public function __call($name, $params) public function __call($name, $params)
{ {
$class = $this->modelClass; if (method_exists($this->modelClass, $name)) {
$scopes = $class::scopes(); $this->scopes[$name] = $params;
if (isset($scopes[$name])) { return $this;
array_unshift($params, $this);
return call_user_func_array($scopes[$name], $params);
} else { } else {
return parent::__call($name, $params); return parent::__call($name, $params);
} }

6
framework/db/ar/ActiveRecord.php

@ -164,10 +164,8 @@ abstract class ActiveRecord extends Model
* echo Customer::count('COUNT(DISTINCT age)')->value(); * echo Customer::count('COUNT(DISTINCT age)')->value();
* ~~~ * ~~~
* *
* @param mixed $q the query parameter. This can be one of the followings: * @param array $q the query configuration. This should be an array of name-value pairs.
* * It will be used to configure the [[ActiveQuery]] object for query purpose.
* - a scalar value (integer or string): query by a single primary key value.
* - an array of name-value pairs: it will be used to configure the [[ActiveQuery]] object for query purpose.
* *
* @return integer the counting result * @return integer the counting result
*/ */

9
tests/unit/data/ar/Customer.php

@ -21,13 +21,8 @@ class Customer extends ActiveRecord
); );
} }
public static function scopes() public function active($query)
{ {
$status = self::STATUS_ACTIVE; return $query->andWhere('@.`status` = ' . self::STATUS_ACTIVE);
return array(
'active' => function($q) use ($status){
return $q->andWhere('@.`status` = ' . $status);
},
);
} }
} }

21
tests/unit/framework/db/ar/ActiveRecordTest.php

@ -35,7 +35,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
public function testUpdate() public function testUpdate()
{ {
// save // save
$customer = Customer::find(2)->one(); $customer = Customer::find(2);
$this->assertTrue($customer instanceof Customer); $this->assertTrue($customer instanceof Customer);
$this->assertEquals('user2', $customer->name); $this->assertEquals('user2', $customer->name);
$this->assertFalse($customer->isNewRecord); $this->assertFalse($customer->isNewRecord);
@ -43,7 +43,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$customer->save(); $customer->save();
$this->assertEquals('user2x', $customer->name); $this->assertEquals('user2x', $customer->name);
$this->assertFalse($customer->isNewRecord); $this->assertFalse($customer->isNewRecord);
$customer2 = Customer::find(2)->one(); $customer2 = Customer::find(2);
$this->assertEquals('user2x', $customer2->name); $this->assertEquals('user2x', $customer2->name);
// updateCounters // updateCounters
@ -57,13 +57,13 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertEquals(0, $orderItem->quantity); $this->assertEquals(0, $orderItem->quantity);
// updateAll // updateAll
$customer = Customer::find(3)->one(); $customer = Customer::find(3);
$this->assertEquals('user3', $customer->name); $this->assertEquals('user3', $customer->name);
$ret = Customer::updateAll(array( $ret = Customer::updateAll(array(
'name' => 'temp', 'name' => 'temp',
), array('id' => 3)); ), array('id' => 3));
$this->assertEquals(1, $ret); $this->assertEquals(1, $ret);
$customer = Customer::find(3)->one(); $customer = Customer::find(3);
$this->assertEquals('temp', $customer->name); $this->assertEquals('temp', $customer->name);
// updateCounters // updateCounters
@ -81,11 +81,11 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
public function testDelete() public function testDelete()
{ {
// delete // delete
$customer = Customer::find(2)->one(); $customer = Customer::find(2);
$this->assertTrue($customer instanceof Customer); $this->assertTrue($customer instanceof Customer);
$this->assertEquals('user2', $customer->name); $this->assertEquals('user2', $customer->name);
$customer->delete(); $customer->delete();
$customer = Customer::find(2)->one(); $customer = Customer::find(2);
$this->assertNull($customer); $this->assertNull($customer);
// deleteAll // deleteAll
@ -140,7 +140,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertTrue($result[2] instanceof Customer); $this->assertTrue($result[2] instanceof Customer);
// find by a single primary key // find by a single primary key
$customer = Customer::find(2)->one(); $customer = Customer::find(2);
$this->assertTrue($customer instanceof Customer); $this->assertTrue($customer instanceof Customer);
$this->assertEquals('user2', $customer->name); $this->assertEquals('user2', $customer->name);
@ -161,7 +161,6 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
// find count // find count
$this->assertEquals(3, Customer::find()->count()); $this->assertEquals(3, Customer::find()->count());
$this->assertEquals(3, Customer::count()); $this->assertEquals(3, Customer::count());
$this->assertEquals(1, Customer::count(2));
$this->assertEquals(2, Customer::count(array( $this->assertEquals(2, Customer::count(array(
'where' => 'id=1 OR id=2', 'where' => 'id=1 OR id=2',
))); )));
@ -294,12 +293,12 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
public function testLazyLoading() public function testLazyLoading()
{ {
// has one // has one
$order = Order::find(3)->one(); $order = Order::find(3);
$this->assertTrue($order->customer instanceof Customer); $this->assertTrue($order->customer instanceof Customer);
$this->assertEquals(2, $order->customer->id); $this->assertEquals(2, $order->customer->id);
// has many // has many
$customer = Customer::find(2)->one(); $customer = Customer::find(2);
$orders = $customer->orders; $orders = $customer->orders;
$this->assertEquals(2, count($orders)); $this->assertEquals(2, count($orders));
$this->assertEquals(2, $orders[0]->id); $this->assertEquals(2, $orders[0]->id);
@ -316,7 +315,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertEquals(2, $orders[2]->books[0]->id); $this->assertEquals(2, $orders[2]->books[0]->id);
// customized relation query // customized relation query
$customer = Customer::find(2)->one(); $customer = Customer::find(2);
$orders = $customer->orders(array( $orders = $customer->orders(array(
'where' => '@.id = 3', 'where' => '@.id = 3',
)); ));

Loading…
Cancel
Save