From 9b417e5f6d10c85f84d75caa059a302c068323b1 Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Sat, 30 Aug 2025 20:02:12 +0900 Subject: [PATCH] Fix #20505: `ArrayDataProvider` key handling with flexible path support --- framework/CHANGELOG.md | 1 + framework/data/ArrayDataProvider.php | 16 ++++------------ .../framework/data/ArrayDataProviderTest.php | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 1e3de45842..123d161a05 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -22,6 +22,7 @@ Yii Framework 2 Change Log - Bug #20489: Replace deprecated `strftime` with `date` in `YiiRequirementChecker` (max-s-lab) - Bug #20494: Fix `PHPdoc`, add `PHPStan/Psalm` annotations for `authMethods` property in `CompositeAuth` class (terabytesoftw) - Bug #20485: Fix error `Cannot unset string offsets` in `yii\di\Instance:ensure(['__class' => ...], 'some\class\name')` (max-s-lab) +- Enh #20505: `ArrayDataProvider` key handling with flexible path support (fetus-hina) 2.0.53 June 27, 2025 -------------------- diff --git a/framework/data/ArrayDataProvider.php b/framework/data/ArrayDataProvider.php index 657bcd2a1c..a89cf56eb1 100644 --- a/framework/data/ArrayDataProvider.php +++ b/framework/data/ArrayDataProvider.php @@ -53,8 +53,9 @@ use yii\helpers\ArrayHelper; class ArrayDataProvider extends BaseDataProvider { /** - * @var string|callable|null the column that is used as the key of the data models. - * This can be either a column name, or a callable that returns the key value of a given data model. + * @var string|array|callable|null the column that is used as the key of the data models. + * This can be either a column name, a dot-separated path, an array of keys, or a callable + * that returns the key value of a given data model. * If this is not set, the index of the [[models]] array will be used. * @see getKeys() */ @@ -103,16 +104,7 @@ class ArrayDataProvider extends BaseDataProvider protected function prepareKeys($models) { if ($this->key !== null) { - $keys = []; - foreach ($models as $model) { - if (is_string($this->key)) { - $keys[] = $model[$this->key]; - } else { - $keys[] = call_user_func($this->key, $model); - } - } - - return $keys; + return ArrayHelper::getColumn($models, $this->key, false); } return array_keys($models); diff --git a/tests/framework/data/ArrayDataProviderTest.php b/tests/framework/data/ArrayDataProviderTest.php index 84944d511b..1699b4b193 100644 --- a/tests/framework/data/ArrayDataProviderTest.php +++ b/tests/framework/data/ArrayDataProviderTest.php @@ -183,6 +183,25 @@ class ArrayDataProviderTest extends TestCase ]; $dataProvider = new ArrayDataProvider(['allModels' => $mixedArray, 'pagination' => $pagination]); $this->assertEquals(['key1', 9], $dataProvider->getKeys()); + + $nestedArray = [ + ['foo' => ['bar' => 'key1']], + ['foo' => ['bar' => 'key2']], + ['foo' => ['bar' => 'key3']], + ]; + $dataProvider = new ArrayDataProvider([ + 'allModels' => $nestedArray, + 'key' => ['foo', 'bar'], + 'pagination' => $pagination, + ]); + $this->assertEquals(['key1', 'key2'], $dataProvider->getKeys()); + + $dataProvider = new ArrayDataProvider([ + 'allModels' => $nestedArray, + 'key' => 'foo.bar', + 'pagination' => $pagination, + ]); + $this->assertEquals(['key1', 'key2'], $dataProvider->getKeys()); } public function testSortFlags()