Browse Source

support using anonymous function to customize relational queries.

tags/2.0.0-beta
Qiang Xue 13 years ago
parent
commit
0fd8212356
  1. 2
      framework/db/ar/ActiveFinder.php
  2. 10
      framework/db/ar/ActiveRecord.php
  3. 19
      tests/unit/framework/db/ar/ActiveRecordTest.php

2
framework/db/ar/ActiveFinder.php

@ -234,7 +234,7 @@ class ActiveFinder extends \yii\base\Object
/** /**
* @param JoinElement $parent * @param JoinElement $parent
* @param array|string $with * @param array|string $with
* @param array $config * @param array|\Closure $config
* @return null|JoinElement * @return null|JoinElement
* @throws \yii\db\Exception * @throws \yii\db\Exception
*/ */

10
framework/db/ar/ActiveRecord.php

@ -555,7 +555,7 @@ abstract class ActiveRecord extends Model
* If the relation is HAS_MANY or MANY_MANY, it will return an array of objects * If the relation is HAS_MANY or MANY_MANY, it will return an array of objects
* or an empty array. * or an empty array.
* @param ActiveRelation|string $relation the relation object or the name of the relation * @param ActiveRelation|string $relation the relation object or the name of the relation
* @param array $params additional parameters that customize the query conditions as specified in the relation declaration. * @param array|\Closure $params additional parameters that customize the query conditions as specified in the relation declaration.
* @return mixed the related object(s). * @return mixed the related object(s).
* @throws Exception if the relation is not specified in [[relations()]]. * @throws Exception if the relation is not specified in [[relations()]].
*/ */
@ -569,8 +569,12 @@ abstract class ActiveRecord extends Model
$relation = $md->relations[$relation]; $relation = $md->relations[$relation];
} }
$relation = clone $relation; $relation = clone $relation;
foreach ($params as $name => $value) { if ($params instanceof \Closure) {
$relation->$name = $value; call_user_func($params, $relation);
} else {
foreach ($params as $name => $value) {
$relation->$name = $value;
}
} }
$finder = new ActiveFinder($this->getDbConnection()); $finder = new ActiveFinder($this->getDbConnection());

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

@ -258,6 +258,14 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
// has many and base limited // has many and base limited
$orders = Order::find()->with('items')->order('@.id')->limit(2)->all(); $orders = Order::find()->with('items')->order('@.id')->limit(2)->all();
$this->assertEquals(2, count($orders)); $this->assertEquals(2, count($orders));
$this->assertEquals(1, $orders[0]->items[0]->id);
/// customize "with" query
$orders = Order::find()->with(array('items' => function($q) {
$q->order('@.id DESC');
}))->order('@.id')->limit(2)->all();
$this->assertEquals(2, count($orders));
$this->assertEquals(2, $orders[0]->items[0]->id);
// findBySql with // findBySql with
$orders = Order::findBySql('SELECT * FROM tbl_order WHERE customer_id=2')->with('items')->all(); $orders = Order::findBySql('SELECT * FROM tbl_order WHERE customer_id=2')->with('items')->all();
@ -314,11 +322,13 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
)); ));
$this->assertEquals(1, count($orders)); $this->assertEquals(1, count($orders));
$this->assertEquals(3, $orders[0]->id); $this->assertEquals(3, $orders[0]->id);
// original results are kept after customized query // original results are kept after customized query
$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);
$this->assertEquals(3, $orders[1]->id); $this->assertEquals(3, $orders[1]->id);
// as array // as array
$orders = $customer->orders(array( $orders = $customer->orders(array(
'asArray' => true, 'asArray' => true,
@ -327,5 +337,14 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertTrue(is_array($orders[0])); $this->assertTrue(is_array($orders[0]));
$this->assertEquals(2, $orders[0]['id']); $this->assertEquals(2, $orders[0]['id']);
$this->assertEquals(3, $orders[1]['id']); $this->assertEquals(3, $orders[1]['id']);
// using anonymous function to customize query condition
$orders = $customer->orders(function($q) {
$q->order('@.id DESC')->asArray();
});
$this->assertEquals(2, count($orders));
$this->assertTrue(is_array($orders[0]));
$this->assertEquals(3, $orders[0]['id']);
$this->assertEquals(2, $orders[1]['id']);
} }
} }
Loading…
Cancel
Save