пн, 10 нояб. 2025 г. в 08:44, Mikhail Savin <[email protected]>:
> 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
