чт, 6 нояб. 2025 г., 19:30 Larry Garfield <[email protected]>:
> On Wed, Nov 5, 2025, at 10:09 PM, Mikhail Savin 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
>
> Correction: The manual does not show an EnumValuesTrait that I can find.
> There is a *comment* in the manual that includes this method, but that's
> not part of the manual proper, and frankly 90% of comments in the manual
> should be removed. (cf:
> https://www.php.net/manual/en/language.enumerations.traits.php#129250)
>
> > 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
>
> I am unclear why this is a major advantage over
> array_column(Status::cases(), 'value');
>
> > == 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
>
> This is a hard-stop. There are hundreds of thousands of packages in the
> wild that need to support multiple PHP versions. Nearly all packaglist
> packages (which I presume is where you're drawing the research from; either
> that or GitHub which will give a similar result set) support at least two
> consecutive versions, if not 4, 5, or 6.
>
> A hard break like this would essentially mean the packages containing
> those 40,000 enums would be unable to support both PHP 8.5 and 8.6 at the
> same time. That's simply not an acceptable impact on the ecosystem,
> regardless of how nice the feature may or may not be.
>
> --Larry Garfield
>
We could add a virtual $values property. Since enum properties are not
allowed in userland, it will not break any existing code.
—
Valentin
>