пт, 7 нояб. 2025 г. в 07:53, Mikhail Savin <[email protected]>:

>
>
> пт, 7 нояб. 2025 г. в 07:08, Valentin Udaltsov <
> [email protected]>:
>
>> чт, 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
>>
>
> Hi all,
>
> Thank you for the thoughtful feedback. Based on the discussion so far, the
> consensus seems to be: "the feature is useful, but the BC break is too
> large."
>
> To address this, I've adjusted the proposal so that user code is allowed
> to
> redeclare values() on backed enums. This keeps existing projects working
> unchanged while providing the native implementation for new code.
>
> The native values() will only be added when not already defined:
>
> ```c
>   if (!zend_hash_exists(&ce->function_table, ZSTR_KNOWN(ZEND_STR_VALUES)))
> {
>     ...
> }
> ```
>
> Result:
>   * Zero BC break - existing code unchanged
>   * New enums get values() automatically
>   * Libraries can maintain their implementation for older PHP support
>
> Trade-off:
> I recognize this makes values() the only overridable enum intrinsic
> (unlike cases/from/tryFrom). I'll document this clearly and add tests
> to lock down the behavior. If needed, we can deprecate user-defined
> values() in a later 8.x and make it an error in PHP 9.0.
>
> Questions:
> 1. Is allowing values() override technically acceptable?
> 2. Is documenting the inconsistency sufficient?
> 3. Should we add deprecation?
> 4. Can I submit RFC for this feature?
> 5. Should I rather implement it via virtual property, as Valentin
> suggested above?
>
> I updated the PR, and also added a few tests for this behavior.
>
> Thoughts?
>
> Best regards,
> Savin Mikhail
>

Hi

I am going to create RFC page, cuz badge "Status: requires RFC" was added
to PR: https://github.com/php/php-src/pull/20398
Could someone please grant me RFC wiki karma so I can create the page
https://wiki.php.net/rfc/add_values_method_to_backed_enum from my account
(login - msavin)?

Reply via email to