Commit aa568aac by Qiang Xue

Added support for using callables as "ActiveQuery::indexBy".

parent 23deeab4
...@@ -55,8 +55,9 @@ class ActiveQuery extends Query ...@@ -55,8 +55,9 @@ class ActiveQuery extends Query
*/ */
public $with; public $with;
/** /**
* @var string the name of the column by which query results should be indexed by. * @var string|callable $column the name of the column by which the query results should be indexed by.
* This is only used when the query result is returned as an array when calling [[all()]]. * This can also be a callable (e.g. anonymous function) that returns the index value based on the given
* row or model data. For more details, see [[indexBy()]].
*/ */
public $indexBy; public $indexBy;
/** /**
...@@ -288,7 +289,19 @@ class ActiveQuery extends Query ...@@ -288,7 +289,19 @@ class ActiveQuery extends Query
/** /**
* Sets the [[indexBy]] property. * Sets the [[indexBy]] property.
* @param string $column the name of the column by which the query results should be indexed by. * @param string|callable $column the name of the column by which the query results should be indexed by.
* This can also be a callable (e.g. anonymous function) that returns the index value based on the given
* row or model data. The signature of the callable should be:
*
* ~~~
* // $model is an AR instance when `asArray` is false,
* // or an array of column values when `asArray` is true.
* function ($model)
* {
* // return the index value corresponding to $model
* }
* ~~~
*
* @return ActiveQuery the query object itself * @return ActiveQuery the query object itself
*/ */
public function indexBy($column) public function indexBy($column)
...@@ -305,7 +318,12 @@ class ActiveQuery extends Query ...@@ -305,7 +318,12 @@ class ActiveQuery extends Query
return $rows; return $rows;
} }
foreach ($rows as $row) { foreach ($rows as $row) {
$models[$row[$this->indexBy]] = $row; if (is_string($this->indexBy)) {
$key = $row[$this->indexBy];
} else {
$key = call_user_func($this->indexBy, $row);
}
$models[$key] = $row;
} }
} else { } else {
/** @var $class ActiveRecord */ /** @var $class ActiveRecord */
...@@ -317,7 +335,12 @@ class ActiveQuery extends Query ...@@ -317,7 +335,12 @@ class ActiveQuery extends Query
} else { } else {
foreach ($rows as $row) { foreach ($rows as $row) {
$model = $class::create($row); $model = $class::create($row);
$models[$model->{$this->indexBy}] = $model; if (is_string($this->indexBy)) {
$key = $model->{$this->indexBy};
} else {
$key = call_user_func($this->indexBy, $model);
}
$models[$key] = $model;
} }
} }
} }
......
...@@ -84,6 +84,15 @@ class ActiveRecordTest extends DatabaseTestCase ...@@ -84,6 +84,15 @@ class ActiveRecordTest extends DatabaseTestCase
$this->assertTrue($customers['user1'] instanceof Customer); $this->assertTrue($customers['user1'] instanceof Customer);
$this->assertTrue($customers['user2'] instanceof Customer); $this->assertTrue($customers['user2'] instanceof Customer);
$this->assertTrue($customers['user3'] instanceof Customer); $this->assertTrue($customers['user3'] instanceof Customer);
// indexBy callable
$customers = Customer::find()->indexBy(function($customer) {
return $customer->id . '-' . $customer->name;
})->orderBy('id')->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers['1-user1'] instanceof Customer);
$this->assertTrue($customers['2-user2'] instanceof Customer);
$this->assertTrue($customers['3-user3'] instanceof Customer);
} }
public function testFindBySql() public function testFindBySql()
......
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