Fix #18499: When using yii\db\Query::all() and yii\db\Query::$indexBy, the yii\db\Query::$indexBy is auto inserted into yii\db\Query::$select - the same as in yii\db\Query::column()

Co-authored-by: Bizley <pawel@positive.codes>
Co-authored-by: Alexander Makarov <sam@rmcreative.ru>
This commit is contained in:
Ondřej Vašíček
2021-02-23 16:44:39 +01:00
committed by GitHub
parent 4ed14bb738
commit d1037db68d
7 changed files with 37 additions and 0 deletions

View File

@ -716,6 +716,8 @@ $query = (new \yii\db\Query())
->all();
```
The column name passed into [[yii\db\Query::indexBy()|indexBy()]] method has to be a part of the `SELECT` fragment of a SQL statement. If [[yii\db\Query::select()|select()]] is not used, all columns are selected and therefore the condition is met. If [[yii\db\Query::select()|select()]] is used with an array in its parameter, Yii handles adding that required SQL fragment for you. This applies when using [[yii\db\Query::indexBy()|indexBy()]] with [[yii\db\Query::all()|all()]] or [[yii\db\Query::column()|column()]]. In other cases, like the following example with an anonymous function, is up to users themselves to take care of it.
To index by expression values, pass an anonymous function to the [[yii\db\Query::indexBy()|indexBy()]] method:
```php

View File

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.41 under development
------------------------
- Enh #18499: When using `yii\db\Query::all()` and `yii\db\Query::$indexBy`, the `yii\db\Query::$indexBy` is auto inserted into `yii\db\Query::$select` - the same as in `yii\db\Query::column()` (OndrejVasicek, samdark, bizley)
- Enh #18483: Add `yii\log\Logger::$dbEventNames` that allows specifying event names used to get statistical results (profiling) of DB queries (atiline)
- Enh #18455: Add ability to use separate attributes for data model and filter model of `yii\grid\GridView` in `yii\grid\DataColumn` (PowerGamer1)
- Enh #18447: Do not use `getLastInsertID` to get PK from insert query to lower collision probability for concurrent inserts (darkdef)

View File

@ -53,6 +53,8 @@ interface ActiveQueryInterface extends QueryInterface
* // return the index value corresponding to $model
* }
* ```
* The column has to be a part of the `SELECT` fragment of a SQL statement.
* If [[yii\db\Query::select()|select()]] is used with an array in its parameter, Yii handles adding that required SQL fragment for you.
*
* @return $this the query object itself
*/

View File

@ -245,7 +245,16 @@ class Query extends Component implements QueryInterface, ExpressionInterface
if ($this->emulateExecution) {
return [];
}
if (is_string($this->indexBy) && $this->indexBy && is_array($this->select) && !in_array($this->indexBy, $this->select)) {
if (strpos($this->indexBy, '.') === false && count($tables = $this->getTablesUsedInFrom()) > 0) {
$this->select[] = key($tables) . '.' . $this->indexBy;
} else {
$this->select[] = $this->indexBy;
}
}
$rows = $this->createCommand($db)->queryAll();
return $this->populate($rows);
}

View File

@ -68,6 +68,8 @@ interface QueryInterface
* // return the index value corresponding to $row
* }
* ```
* The column has to be a part of the `SELECT` fragment of a SQL statement.
* If [[yii\db\Query::select()|select()]] is used with an array in its parameter, Yii handles adding that required SQL fragment for you.
*
* @return $this the query object itself
*/

View File

@ -71,6 +71,8 @@ trait QueryTrait
* // return the index value corresponding to $row
* }
* ```
* The column has to be a part of the `SELECT` fragment of a SQL statement.
* If [[yii\db\Query::select()|select()]] is used with an array in its parameter, Yii handles adding that required SQL fragment for you.
*
* @return $this the query object itself
*/

View File

@ -795,4 +795,23 @@ abstract class QueryTest extends DatabaseTestCase
$newQuery->withQueries
);
}
/**
* @see https://github.com/yiisoft/yii2/issues/18499
*/
public function testAllWithAutomaticallyAddedIndexedByColumn()
{
$db = $this->getConnection();
$result = (new Query())->from('customer')
->select('name')
->orderBy(['id' => SORT_DESC])
->indexBy('id')
->all($db);
$this->assertEquals([
3 => ['name' => 'user3', 'id' => 3],
2 => ['name' => 'user2', 'id' => 2],
1 => ['name' => 'user1', 'id' => 1]
], $result);
}
}