From 43cfd15615452275d964b039ddc5b021b5e1154b Mon Sep 17 00:00:00 2001 From: WarLikeLaux Date: Wed, 4 Mar 2026 23:30:50 +0600 Subject: [PATCH 1/5] Add enum support in `ArrayHelper::toArray()` --- framework/CHANGELOG.md | 1 + framework/helpers/BaseArrayHelper.php | 6 +++ tests/framework/helpers/ArrayHelperTest.php | 57 +++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index fb5b1fc96a1..f9fe0c5d47b 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -23,6 +23,7 @@ Yii Framework 2 Change Log - Bug #20750: Fix `@return` annotation for `yii\console\Controller::runAction()` (mspirkov) - Bug #20750: Add the missing `@property-write` annotation to `yii\console\Controller` (mspirkov) - Bug #20751: Fix `@param` annotation for `$param` parameter in `Sort::parseSortParam()` (mspirkov) +- Enh #20781: Add enum support in `ArrayHelper::toArray()` (WarLikeLaux) 2.0.54 January 09, 2026 diff --git a/framework/helpers/BaseArrayHelper.php b/framework/helpers/BaseArrayHelper.php index ac369120231..f8c0fa4daad 100644 --- a/framework/helpers/BaseArrayHelper.php +++ b/framework/helpers/BaseArrayHelper.php @@ -8,6 +8,8 @@ namespace yii\helpers; +use BackedEnum; +use UnitEnum; use Yii; use ArrayAccess; use Traversable; @@ -71,6 +73,10 @@ public static function toArray($object, $properties = [], $recursive = true) } return $object; + } elseif ($object instanceof BackedEnum) { + return $object->value; + } elseif ($object instanceof UnitEnum) { + return $object->name; } elseif ($object instanceof \DateTimeInterface) { return (array)$object; } elseif (is_object($object)) { diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php index 34cbf0b7c1f..cfc06172259 100644 --- a/tests/framework/helpers/ArrayHelperTest.php +++ b/tests/framework/helpers/ArrayHelperTest.php @@ -132,6 +132,45 @@ public function testToArray(): void ], ArrayHelper::toArray(new DateTime('2021-09-13 15:16:17', new DateTimeZone('UTC')))); } + public function testToArrayStringBackedEnum(): void + { + $this->assertSame('hearts', ArrayHelper::toArray(StringBackedEnum::Hearts)); + } + + public function testToArrayIntBackedEnum(): void + { + $this->assertSame(1, ArrayHelper::toArray(IntBackedEnum::Active)); + } + + public function testToArrayUnitEnum(): void + { + $this->assertSame('Red', ArrayHelper::toArray(PureEnum::Red)); + } + + public function testToArrayWithBackedEnumInArray(): void + { + $this->assertSame( + ['hearts', 'diamonds'], + ArrayHelper::toArray([StringBackedEnum::Hearts, StringBackedEnum::Diamonds]) + ); + } + + public function testToArrayWithUnitEnumInArray(): void + { + $this->assertSame( + ['Red', 'Blue'], + ArrayHelper::toArray([PureEnum::Red, PureEnum::Blue]) + ); + } + + public function testToArrayWithMixedEnumInArray(): void + { + $this->assertSame( + ['hearts', 1, 'Red'], + ArrayHelper::toArray([StringBackedEnum::Hearts, IntBackedEnum::Active, PureEnum::Red]) + ); + } + public function testRemove(): void { $array = ['name' => 'b', 'age' => 3]; @@ -1876,3 +1915,21 @@ public function getMoreMagic() return 'ta-da'; } } + +enum StringBackedEnum: string +{ + case Hearts = 'hearts'; + case Diamonds = 'diamonds'; +} + +enum IntBackedEnum: int +{ + case Active = 1; + case Inactive = 0; +} + +enum PureEnum +{ + case Red; + case Blue; +} From a3e5b3c71570e48d8bc4dc6eb8726c62064e1277 Mon Sep 17 00:00:00 2001 From: WarLikeLaux Date: Wed, 4 Mar 2026 23:31:34 +0600 Subject: [PATCH 2/5] Change changelog entry #20781 from Enh to Bug --- framework/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index f9fe0c5d47b..6fc3c51a6a5 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -23,7 +23,7 @@ Yii Framework 2 Change Log - Bug #20750: Fix `@return` annotation for `yii\console\Controller::runAction()` (mspirkov) - Bug #20750: Add the missing `@property-write` annotation to `yii\console\Controller` (mspirkov) - Bug #20751: Fix `@param` annotation for `$param` parameter in `Sort::parseSortParam()` (mspirkov) -- Enh #20781: Add enum support in `ArrayHelper::toArray()` (WarLikeLaux) +- Bug #20781: Fix enum handling in `ArrayHelper::toArray()` (WarLikeLaux) 2.0.54 January 09, 2026 From 1e21cb373022b16d5401aa784da3c9d5eccec91e Mon Sep 17 00:00:00 2001 From: WarLikeLaux Date: Wed, 4 Mar 2026 23:55:25 +0600 Subject: [PATCH 3/5] Fix enum tests for PHP 7.4/8.0 compatibility --- tests/framework/helpers/ArrayHelperTest.php | 39 ++++++++++--------- .../framework/helpers/enums/IntBackedEnum.php | 9 +++++ tests/framework/helpers/enums/PureEnum.php | 9 +++++ .../helpers/enums/StringBackedEnum.php | 9 +++++ 4 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 tests/framework/helpers/enums/IntBackedEnum.php create mode 100644 tests/framework/helpers/enums/PureEnum.php create mode 100644 tests/framework/helpers/enums/StringBackedEnum.php diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php index cfc06172259..f149513262b 100644 --- a/tests/framework/helpers/ArrayHelperTest.php +++ b/tests/framework/helpers/ArrayHelperTest.php @@ -22,6 +22,9 @@ use yii\base\Model; use yii\data\Sort; use yii\helpers\ArrayHelper; +use yiiunit\framework\helpers\enums\IntBackedEnum; +use yiiunit\framework\helpers\enums\PureEnum; +use yiiunit\framework\helpers\enums\StringBackedEnum; use yiiunit\TestCase; /** @@ -134,21 +137,33 @@ public function testToArray(): void public function testToArrayStringBackedEnum(): void { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } $this->assertSame('hearts', ArrayHelper::toArray(StringBackedEnum::Hearts)); } public function testToArrayIntBackedEnum(): void { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } $this->assertSame(1, ArrayHelper::toArray(IntBackedEnum::Active)); } public function testToArrayUnitEnum(): void { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } $this->assertSame('Red', ArrayHelper::toArray(PureEnum::Red)); } public function testToArrayWithBackedEnumInArray(): void { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } $this->assertSame( ['hearts', 'diamonds'], ArrayHelper::toArray([StringBackedEnum::Hearts, StringBackedEnum::Diamonds]) @@ -157,6 +172,9 @@ public function testToArrayWithBackedEnumInArray(): void public function testToArrayWithUnitEnumInArray(): void { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } $this->assertSame( ['Red', 'Blue'], ArrayHelper::toArray([PureEnum::Red, PureEnum::Blue]) @@ -165,6 +183,9 @@ public function testToArrayWithUnitEnumInArray(): void public function testToArrayWithMixedEnumInArray(): void { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } $this->assertSame( ['hearts', 1, 'Red'], ArrayHelper::toArray([StringBackedEnum::Hearts, IntBackedEnum::Active, PureEnum::Red]) @@ -1915,21 +1936,3 @@ public function getMoreMagic() return 'ta-da'; } } - -enum StringBackedEnum: string -{ - case Hearts = 'hearts'; - case Diamonds = 'diamonds'; -} - -enum IntBackedEnum: int -{ - case Active = 1; - case Inactive = 0; -} - -enum PureEnum -{ - case Red; - case Blue; -} diff --git a/tests/framework/helpers/enums/IntBackedEnum.php b/tests/framework/helpers/enums/IntBackedEnum.php new file mode 100644 index 00000000000..2115c5fee44 --- /dev/null +++ b/tests/framework/helpers/enums/IntBackedEnum.php @@ -0,0 +1,9 @@ + Date: Thu, 5 Mar 2026 00:05:30 +0600 Subject: [PATCH 4/5] Fix phpstan and PHP 7.4 compatibility for enum handling --- framework/helpers/BaseArrayHelper.php | 16 +++++++++------- tests/framework/helpers/ArrayHelperTest.php | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/framework/helpers/BaseArrayHelper.php b/framework/helpers/BaseArrayHelper.php index f8c0fa4daad..864c725323b 100644 --- a/framework/helpers/BaseArrayHelper.php +++ b/framework/helpers/BaseArrayHelper.php @@ -8,8 +8,6 @@ namespace yii\helpers; -use BackedEnum; -use UnitEnum; use Yii; use ArrayAccess; use Traversable; @@ -66,17 +64,21 @@ public static function toArray($object, $properties = [], $recursive = true) if (is_array($object)) { if ($recursive) { foreach ($object as $key => $value) { - if (is_array($value) || is_object($value)) { + if (PHP_VERSION_ID >= 80100 && $value instanceof \BackedEnum) { + $object[$key] = $value->value; + } elseif (PHP_VERSION_ID >= 80100 && $value instanceof \UnitEnum) { + $object[$key] = $value->name; + } elseif (is_array($value) || is_object($value)) { $object[$key] = static::toArray($value, $properties, true); } } } return $object; - } elseif ($object instanceof BackedEnum) { - return $object->value; - } elseif ($object instanceof UnitEnum) { - return $object->name; + } elseif (PHP_VERSION_ID >= 80100 && $object instanceof \BackedEnum) { + return [$object->value]; + } elseif (PHP_VERSION_ID >= 80100 && $object instanceof \UnitEnum) { + return [$object->name]; } elseif ($object instanceof \DateTimeInterface) { return (array)$object; } elseif (is_object($object)) { diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php index f149513262b..063cdd649bc 100644 --- a/tests/framework/helpers/ArrayHelperTest.php +++ b/tests/framework/helpers/ArrayHelperTest.php @@ -140,7 +140,7 @@ public function testToArrayStringBackedEnum(): void if (version_compare(PHP_VERSION, '8.1.0', '<')) { $this->markTestSkipped('Enums require PHP 8.1+'); } - $this->assertSame('hearts', ArrayHelper::toArray(StringBackedEnum::Hearts)); + $this->assertSame(['hearts'], ArrayHelper::toArray(StringBackedEnum::Hearts)); } public function testToArrayIntBackedEnum(): void @@ -148,7 +148,7 @@ public function testToArrayIntBackedEnum(): void if (version_compare(PHP_VERSION, '8.1.0', '<')) { $this->markTestSkipped('Enums require PHP 8.1+'); } - $this->assertSame(1, ArrayHelper::toArray(IntBackedEnum::Active)); + $this->assertSame([1], ArrayHelper::toArray(IntBackedEnum::Active)); } public function testToArrayUnitEnum(): void @@ -156,7 +156,7 @@ public function testToArrayUnitEnum(): void if (version_compare(PHP_VERSION, '8.1.0', '<')) { $this->markTestSkipped('Enums require PHP 8.1+'); } - $this->assertSame('Red', ArrayHelper::toArray(PureEnum::Red)); + $this->assertSame(['Red'], ArrayHelper::toArray(PureEnum::Red)); } public function testToArrayWithBackedEnumInArray(): void From 743afc52ec16c3e2dcb5c96c2f07af7ab530aa52 Mon Sep 17 00:00:00 2001 From: WarLikeLaux Date: Thu, 5 Mar 2026 00:10:31 +0600 Subject: [PATCH 5/5] Add phpstan 7.4 baseline entries for enum classes in `BaseArrayHelper` --- phpstan-baseline-7x.neon | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/phpstan-baseline-7x.neon b/phpstan-baseline-7x.neon index d09a46b3bf0..491098049ed 100644 --- a/phpstan-baseline-7x.neon +++ b/phpstan-baseline-7x.neon @@ -40,6 +40,26 @@ parameters: count: 1 path: framework/db/Command.php + - + message: "#^Class BackedEnum not found\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + + - + message: "#^Access to property \\$value on an unknown class BackedEnum\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + + - + message: "#^Class UnitEnum not found\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + + - + message: "#^Access to property \\$name on an unknown class UnitEnum\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + - message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#" count: 2