From 0fd82123560720d0e755f302c2a6bee6894b1f2a Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Mon, 2 Apr 2012 21:25:58 -0400 Subject: [PATCH] support using anonymous function to customize relational queries. --- framework/db/ar/ActiveFinder.php | 2 +- framework/db/ar/ActiveRecord.php | 10 +++++++--- tests/unit/framework/db/ar/ActiveRecordTest.php | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/framework/db/ar/ActiveFinder.php b/framework/db/ar/ActiveFinder.php index e110116..f584932 100644 --- a/framework/db/ar/ActiveFinder.php +++ b/framework/db/ar/ActiveFinder.php @@ -234,7 +234,7 @@ class ActiveFinder extends \yii\base\Object /** * @param JoinElement $parent * @param array|string $with - * @param array $config + * @param array|\Closure $config * @return null|JoinElement * @throws \yii\db\Exception */ diff --git a/framework/db/ar/ActiveRecord.php b/framework/db/ar/ActiveRecord.php index d6d504e..9d004da 100644 --- a/framework/db/ar/ActiveRecord.php +++ b/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 * or an empty array. * @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). * @throws Exception if the relation is not specified in [[relations()]]. */ @@ -569,8 +569,12 @@ abstract class ActiveRecord extends Model $relation = $md->relations[$relation]; } $relation = clone $relation; - foreach ($params as $name => $value) { - $relation->$name = $value; + if ($params instanceof \Closure) { + call_user_func($params, $relation); + } else { + foreach ($params as $name => $value) { + $relation->$name = $value; + } } $finder = new ActiveFinder($this->getDbConnection()); diff --git a/tests/unit/framework/db/ar/ActiveRecordTest.php b/tests/unit/framework/db/ar/ActiveRecordTest.php index c4c448b..a165764 100644 --- a/tests/unit/framework/db/ar/ActiveRecordTest.php +++ b/tests/unit/framework/db/ar/ActiveRecordTest.php @@ -258,6 +258,14 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase // has many and base limited $orders = Order::find()->with('items')->order('@.id')->limit(2)->all(); $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 $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(3, $orders[0]->id); + // original results are kept after customized query $orders = $customer->orders; $this->assertEquals(2, count($orders)); $this->assertEquals(2, $orders[0]->id); $this->assertEquals(3, $orders[1]->id); + // as array $orders = $customer->orders(array( 'asArray' => true, @@ -327,5 +337,14 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase $this->assertTrue(is_array($orders[0])); $this->assertEquals(2, $orders[0]['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']); } } \ No newline at end of file