Re: [RFC] [Discussion] BackedEnum::values() - Seeking feedback before formal RFC
| From: | Nick | Date: | Thu, 06 Nov 2025 06:01:22 +0000 |
| Subject: | Re: [RFC] [Discussion] BackedEnum::values() - Seeking feedback before formal RFC | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-129110@lists.php.net to get a copy of this message | ||
> On 6. Nov 2025, at 11:09, Mikhail Savin <mikhail.d.savin@gmail.com> wrote:
>
> Hi internals,
>
> I would like to propose adding a native values() method to the BackedEnum
> interface that returns an array of all backing values. Before creating a
> formal RFC, I'm seeking feedback on the concept and approach.
>
> == Summary ==
>
> The proposal adds:
>
> interface BackedEnum {
> public static function values(): array;
> }
>
> This would allow:
>
> enum Status: string {
> case Active = 'active';
> case Inactive = 'inactive';
> }
>
> Status::values(); // ['active', 'inactive']
>
> == Motivation ==
>
> This pattern is extremely common in the wild. Based on GitHub code search:
>
> * ~3,860+ direct implementations of this exact pattern
> * ~20,000-40,000 estimated real usage when accounting for shared traits
> * Used in major frameworks: Symfony core (TypeIdentifier.php),
> Laravel ecosystem
> * Documented by PHP.net: The manual itself shows EnumValuesTrait as
> an example
>
> Common use cases:
> * Database migrations: $table->enum('status', Status::values())
> * Form validation: $validator->rule('status', 'in', Status::values())
> * API responses: ['allowed_statuses' => Status::values()]
>
> == Implementation ==
>
> I have a working implementation with tests:
> https://github.com/php/php-src/pull/20398
>
> The implementation:
> * Mirrors the existing cases() method structure
> * Extracts the value property from each case
> * Returns an indexed array (0, 1, 2, ...)
> * Only available on BackedEnum, not UnitEnum
> * All tests pass
>
> == Backward Compatibility - Important Discussion Point ==
>
> This is a breaking change. Enums that already define a values() method
> will fail with:
>
> Fatal error: Cannot redeclare BackedEnum::values()
>
> Based on ecosystem research:
> * ~24,000-44,000 enum instances will break
> * All implementations are functionally identical to what's being proposed
> * Migration is mechanical: just delete the user-defined method
>
> The break is justified because:
>
> 1. Behavior is unchanged - native implementation does exactly what users
> already implemented
> 2. Migration is trivial - simply remove the redundant method
> 3. Precedent exists - PHP 8.1 native enums broke myclabs/php-enum
> (4.9k stars) similarly
> 4. Long-term benefit - standardization, discoverability, elimination
> of boilerplate
> 5. No alternative - virtual properties are technically infeasible;
> different name doesn't match community expectations
>
> == Questions for Discussion ==
>
> 1. BC break acceptability: Given the scope and straightforward migration,
> is this break acceptable?
>
> 2. Method name: values() matches community usage (3,860+ examples) and
> parallels cases(). Alternatives like getValues() or toArray() were
> considered but seem inferior. Thoughts?
>
> 3. Target version: Currently targeting PHP 8.6 (master branch). Is this
> appropriate?
>
> 4. Deprecation period: Should we emit E_DEPRECATED in 8.5 and fatal error
> in 9.0? Or accept the break immediately? (Deprecation adds engine
> complexity and delays benefit.)
>
> == Prior Art ==
>
> * Symfony: Uses this pattern in core components
> * PHP.net Manual: Documents EnumValuesTrait approach
> * TypeScript: Object.values(Enum)
> * Python: [e.value for e in Enum]
> * myclabs/php-enum: Had values() method (4.9k stars)
>
> == Next Steps ==
>
> If feedback is generally positive, I will:
> 1. Request RFC karma
> 2. Create formal RFC on wiki.php.net
> <http://wiki.php.net/>
> 3. Address any concerns raised in this discussion
> 4. Move to formal voting after discussion period
>
> == Implementation Details ==
>
> For those interested in the technical details, the PR includes:
> * Core implementation in zend_enum.c
> * Stub file updates
> * Comprehensive test coverage (9 test files)
> * Reflection support
> * Documentation in NEWS and UPGRADING
>
> PR: https://github.com/php/php-src/pull/20398
>
> Looking forward to your feedback!
>
> Best regards, Savin Mikhail
> GitHub: @savinmikhail
Hey,
Thanks for this! I would love to see this in core.
> 2. Method name: values() matches community usage (3,860+ examples) and
> parallels cases(). Alternatives like getValues() or toArray() were
> considered but seem inferior. Thoughts?
values()
> 1. BC break acceptability: Given the scope and straightforward migration,
> is this break acceptable?
> 3. Target version: Currently targeting PHP 8.6 (master branch). Is this
> appropriate?
>
> 4. Deprecation period: Should we emit E_DEPRECATED in 8.5 and fatal error
> in 9.0? Or accept the break immediately? (Deprecation adds engine
> complexity and delays benefit.)
Perhaps the smoothest way would be to allow from 8.6 redeclaring values(), in the same
time deprecate it and break it later (9.0)?
Cheers