> On 6. Nov 2025, at 11:09, Mikhail Savin <[email protected]> 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

Reply via email to