将查询结果列表的键(key)指定为某个字段的值
### 1. 使用 `indexBy()` 方法
**示例:** 将用户列表的键设为 `id` 字段的值。
```php
// 使用 Query Builder
$users = (new \yii\db\Query())
->select(['id', 'name', 'email'])
->from('user')
->indexBy('id') // 指定索引字段
->all();
// 返回结果类似:
// [
// 1 => ['id' => 1, 'name' => 'Alice', 'email' => '...'],
// 2 => ['id' => 2, 'name' => 'Bob', 'email' => '...'],
// ]
```
**ActiveRecord 示例:**
```php
// 使用 ActiveRecord
$users = User::find()
->select(['id', 'name', 'email'])
->indexBy('id')
->asArray() // 可选,返回数组而非模型对象
->all();
```
如果不需要 `asArray()`,返回的是模型对象数组,键同样会按指定字段索引:
```php
$users = User::find()->indexBy('id')->all();
// 结果: $users[1] 是 id=1 的用户模型对象
```
---
### 2. 使用 `ArrayHelper::index()` 对已有数组重新索引
如果你已经获取了结果集,可以使用 `yii\helpers\ArrayHelper::index()` 来重新索引:
```php
use yii\helpers\ArrayHelper;
$users = User::find()->asArray()->all();
$indexedUsers = ArrayHelper::index($users, 'id');
// 结果键为 id 的值
```
---
### 3. 使用复杂表达式作为键
`indexBy()` 也可以接收一个**回调函数**,允许你使用组合字段或经过计算的字段作为键:
```php
$users = User::find()
->indexBy(function ($row) {
// $row 是数组或对象(取决于是否 asArray)
return $row['id'] . '_' . $row['name'];
})
->all();
```
---
### 注意事项
- **唯一性**:如果索引字段的值重复,后面的值会覆盖前面的值。
- **性能**:`indexBy()` 是在 PHP 层面重新索引,对大数据集有一定内存开销,但通常可接受。
- **与 `asArray()` 配合**:如果不需要模型对象,建议加上 `asArray()` 提高性能。
---
### 总结
| 场景 | 推荐方法 |
|------|----------|
| 查询时直接指定键 | `->indexBy('field')` |
| 已有结果集重新索引 | `ArrayHelper::index($data, 'field')` |
| 复杂键(组合或计算) | `->indexBy(function(){...})` |
根据需要选择即可。