Re: [RFC] [Discussion] Add values() Method to BackedEnum
пн, 10 нояб. 2025 г. в 08:44, Mikhail Savin <mikhail.d.savin@gmail.com>:
> Hi internals,
>
> I've created an RFC to add a native values() method to BackedEnum:
>
> https://wiki.php.net/rfc/add_values_method_to_backed_enum
>
> == Summary ==
>
> The RFC proposes adding BackedEnum::values() that returns an indexed array
> of all backing values. The implementation uses conditional registration -
> the native method is only added when the enum doesn't already define
> values(), ensuring ZERO backward compatibility breaks.
>
> Key points:
> * Native values() added automatically to new enums
> * Existing enums with custom values() continue working unchanged
> * Trait-based implementations are respected
> * Libraries can maintain their implementation for older PHP versions
> * Solves boilerplate problem (3,860+ implementations, ~24k-44k real
> usage)
>
> Common use cases:
> * Database migrations: $table->enum('status', Status::values())
> * Form validation: in_array($input, Status::values())
> * API responses: ['allowed_values' => Status::values()]
>
> == Implementation ==
>
> Working implementation with conditional registration:
> https://github.com/php/php-src/pull/20398
>
> The engine checks if values() exists before registering the native version:
> - User-defined values() present? Use it.
> - No user-defined values()? Add native implementation.
>
> == No BC Breaks ==
>
> This approach ensures:
> * Existing code works unchanged (no migration needed)
> * Immediate benefit for new code (automatic values())
> * Gradual adoption possible (libraries can migrate at their pace)
>
> Trade-off: Makes values() the only overridable enum method (unlike
> cases/from/tryFrom). The RFC documents this as a pragmatic choice -
> solving real problems without forced migrations.
>
> == Questions ==
>
> 1. Is the conditional approach technically sound?
> 2. Is the API consistency trade-off acceptable given the zero BC breaks?
> 3. Any concerns with the implementation approach?
> 4. Should I implement some steps from "Future scope" of the rfc now?
>
> Discussion period: 2 weeks minimum before voting.
>
> Looking forward to your feedback!
>
> Best regards,
> Savin Mikhail
>
Hi, Mikhail!
Thank you for the RFC.
Consider this code if this RFC is accepted:
enum EnumWithUserDefinedValuesMethod: string
{
case X = 'x';
public static function values(): string
{
return 'values';
}
}
function getBackedEnumValues(BackedEnum $enum): array
{
return $enum::values();
}
getBackedEnumValues(EnumWithUserDefinedValuesMethod::X);
This code will suddenly break, because inside getBackedEnumValues I can
safely assume that BackedEnum::values() returns an array, since it's a part
of the interface contract.
However, EnumWithUserDefinedValuesMethod breaks the Liskov Substitution
Principle by defining a method with a non-compatible return type and gives
a runtime error.
What you've basically suggested is to ignore the LSP. This is not a good
idea.
--
Best regards, Valentin
Thread (12 messages)