mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-24 10:39:03 +08:00
Fixes #3197: Using ActiveQuery::indexBy() may cause relational AR queries to generate incorrect relational results
This commit is contained in:
@@ -20,6 +20,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #3153: Fixed the bug that using "between" operator to build a SQL query will cause a PHP notice (gonimar)
|
||||
- Bug #3184: Fixed the bug that client validation for string length comparison did not set error message correctly (Sergeygithub)
|
||||
- Bug #3194: Date formatter works only for timestamps in the year range 1970 to 2038 (kartik-v)
|
||||
- Bug #3197: Using `ActiveQuery::indexBy()` may cause relational AR queries to generate incorrect relational results (qiangxue)
|
||||
- Bug #3204: `yii\di\Container` did not handle the `$config` parameter well in case when it does not have a default value (qiangxue)
|
||||
- Bug #3216: Fixed the bug that `yii.activeForm.destroy()` did not remove `submit` event handlers (qiangxue)
|
||||
- Bug #3233: Ensure consistent behavior in ActiveRecord::afterSave() (cebe, qiangxue)
|
||||
|
||||
@@ -230,13 +230,23 @@ trait ActiveRelationTrait
|
||||
|
||||
return [$model];
|
||||
} else {
|
||||
// https://github.com/yiisoft/yii2/issues/3197
|
||||
// delay indexing related models after buckets are built
|
||||
$indexBy = $this->indexBy;
|
||||
$this->indexBy = null;
|
||||
$models = $this->all();
|
||||
|
||||
if (isset($viaModels, $viaQuery)) {
|
||||
$buckets = $this->buildBuckets($models, $this->link, $viaModels, $viaQuery->link);
|
||||
} else {
|
||||
$buckets = $this->buildBuckets($models, $this->link);
|
||||
}
|
||||
|
||||
$this->indexBy = $indexBy;
|
||||
if ($this->indexBy !== null && $this->multiple) {
|
||||
$buckets = $this->indexBuckets($buckets, $this->indexBy);
|
||||
}
|
||||
|
||||
$link = array_values(isset($viaQuery) ? $viaQuery->link : $this->link);
|
||||
foreach ($primaryModels as $i => $primaryModel) {
|
||||
if ($this->multiple && count($link) == 1 && is_array($keys = $primaryModel[reset($link)])) {
|
||||
@@ -358,22 +368,14 @@ trait ActiveRelationTrait
|
||||
$key = $this->getModelKey($model, $linkKeys);
|
||||
if (isset($map[$key])) {
|
||||
foreach (array_keys($map[$key]) as $key2) {
|
||||
if ($this->indexBy !== null) {
|
||||
$buckets[$key2][$i] = $model;
|
||||
} else {
|
||||
$buckets[$key2][] = $model;
|
||||
}
|
||||
$buckets[$key2][] = $model;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($models as $i => $model) {
|
||||
$key = $this->getModelKey($model, $linkKeys);
|
||||
if ($this->indexBy !== null) {
|
||||
$buckets[$key][$i] = $model;
|
||||
} else {
|
||||
$buckets[$key][] = $model;
|
||||
}
|
||||
$buckets[$key][] = $model;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,6 +388,19 @@ trait ActiveRelationTrait
|
||||
return $buckets;
|
||||
}
|
||||
|
||||
private function indexBuckets($buckets, $indexBy)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($buckets as $key => $models) {
|
||||
$result[$key] = [];
|
||||
foreach ($models as $model) {
|
||||
$index = is_string($indexBy) ? $model[$indexBy] : call_user_func($indexBy, $model);
|
||||
$result[$key][$index] = $model;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attributes the attributes to prefix
|
||||
* @return array
|
||||
|
||||
Reference in New Issue
Block a user