diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 4f8b839..c67f9d7 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -5,6 +5,7 @@ Yii Framework 2 Change Log ------------------------ - Bug #19138: Allow digits in language code (ntesic) +- Bug #19148: Fix undefined array key errors in `yii\db\ActiveRelationTrait` (stevekr) - Bug #19041: Fix PHP 8.1 issues (longthanhtran, samdark, pamparam83, sartor, githubjeka) diff --git a/framework/db/ActiveRelationTrait.php b/framework/db/ActiveRelationTrait.php index 0e0b5f2..24fa0af 100644 --- a/framework/db/ActiveRelationTrait.php +++ b/framework/db/ActiveRelationTrait.php @@ -289,7 +289,12 @@ trait ActiveRelationTrait $link = array_values($deepViaQuery->link); } foreach ($primaryModels as $i => $primaryModel) { - if ($this->multiple && count($link) === 1 && is_array($keys = $primaryModel[reset($link)])) { + $keys = null; + if ($this->multiple && count($link) === 1) { + $primaryModelKey = reset($link); + $keys = isset($primaryModel[$primaryModelKey]) ? $primaryModel[$primaryModelKey] : null; + } + if (is_array($keys)) { $value = []; foreach ($keys as $key) { $key = $this->normalizeModelKey($key); @@ -523,7 +528,8 @@ trait ActiveRelationTrait // single key $attribute = reset($this->link); foreach ($models as $model) { - if (($value = $model[$attribute]) !== null) { + $value = isset($model[$attribute]) ? $model[$attribute] : null; + if ($value !== null) { if (is_array($value)) { $values = array_merge($values, $value); } elseif ($value instanceof ArrayExpression && $value->getDimension() === 1) { @@ -574,13 +580,15 @@ trait ActiveRelationTrait /** * @param ActiveRecordInterface|array $model * @param array $attributes - * @return string + * @return string|false */ private function getModelKey($model, $attributes) { $key = []; foreach ($attributes as $attribute) { - $key[] = $this->normalizeModelKey($model[$attribute]); + if (isset($model[$attribute])) { + $key[] = $this->normalizeModelKey($model[$attribute]); + } } if (count($key) > 1) { return serialize($key); diff --git a/tests/framework/db/ActiveRecordTest.php b/tests/framework/db/ActiveRecordTest.php index 0088a90..3881be6 100644 --- a/tests/framework/db/ActiveRecordTest.php +++ b/tests/framework/db/ActiveRecordTest.php @@ -1361,7 +1361,7 @@ abstract class ActiveRecordTest extends DatabaseTestCase $model->char_col2 = 'not something'; $model->loadDefaultValues(false); $this->assertEquals('something', $model->char_col2); - + // Cropped model with 2 attributes/columns $model = new CroppedType(); $model->loadDefaultValues(); @@ -1529,6 +1529,29 @@ abstract class ActiveRecordTest extends DatabaseTestCase ]; $this->assertEquals($expected, $aggregation); + // tests with single pk asArray with eager loading + $aggregation = Customer::find() + ->select(['{{customer}}.[[status]]', 'SUM({{order}}.[[total]]) AS [[sumtotal]]']) + ->joinWith('ordersPlain') + ->groupBy('{{customer}}.[[status]]') + ->orderBy('status') + ->asArray() + ->all(); + + $expected = [ + [ + 'status' => 1, + 'sumtotal' => 183, + 'ordersPlain' => [], + ], + [ + 'status' => 2, + 'sumtotal' => 0, + 'ordersPlain' => [], + ], + ]; + $this->assertEquals($expected, $aggregation); + // tests with single pk with Models $aggregation = Customer::find() ->select(['{{customer}}.[[status]]', 'SUM({{order}}.[[total]]) AS [[sumTotal]]'])