-
Notifications
You must be signed in to change notification settings - Fork 8k
Add values() Method to BackedEnum #20398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Great and thorough study — the addition of this method seems highly anticipated, and I believe it's underrated because one of the most common approaches uses array_column :) |
|
I emailed the internals, now I'm waiting for the feedback |
Zend/zend_enum.c
Outdated
|
|
||
| static ZEND_NAMED_FUNCTION(zend_enum_values_func) | ||
| { | ||
| zend_class_entry *ce = execute_data->func->common.scope; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| zend_class_entry *ce = execute_data->func->common.scope; | |
| zend_class_entry *ce = EX(func)->common.scope; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx, fixed it
Zend/zend_enum.c
Outdated
| } | ||
| zval *prop = zend_enum_fetch_case_value(Z_OBJ_P(zv)); | ||
| zval tmp; | ||
| ZVAL_COPY(&tmp, prop); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would likely be better to use Z_ADDREF_P(prop); instead of ZVAL_COPY. Then use prop instead of &tmp below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx, fixed it
|
Based on the feedback from the internals so far: consensus seems to be “the feature is useful, but the BC break is too large.” To address that, I’ve adjusted the proposal so that user code is allowed to redeclare I recognize this makes If, over time, the community prefers to consolidate on a single intrinsic (no redeclaration), we can introduce a deprecation phase in a later minor and make redeclaration an error in the next major. For now, the goal is to deliver the utility of |
|
@vudaltsov suggested to use virtual property $values for that, I am not sure would it be better than the current implementation (with redeclaring values() method), cuz it would be less consistent. Any thoughts? |
Summary
Introduce a native
BackedEnum::values()static method that returns the list of all backing values (int|string) of a backed enum’s cases in declaration order. This eliminates boilerplate commonly implemented across projects and aligns with the existingcases()API.Target: master (PHP 8.6)
Motivation
The ecosystem repeatedly implements the same pattern to produce an array of enum values:
This pattern appears widely across GitHub and frameworks, often implemented directly or via traits (which hides usage from code search). A conservative summary of real-world evidence:
Quantitative (code search + trait multiplier):
array_map(fn($case) => $case->value, self::cases())return array_map+self::cases()+->valuereturn array_map+fn($case) => $case->valuefunction values()+return array_map+self::cases()function toArray()+array_map+self::cases()+->valuefunction getValues()+array_map+self::cases()function values()+foreach+self::cases()+[] = $+->valueTrait pattern multiplier:
EnumValuesTrait) and thenuseit in dozens of enums, so direct search counts significantly understate usage.Qualitative (frameworks & libraries):
Providing a native
values()method:cases()nicely).Proposal
Add the following method to the
BackedEnuminterface:Semantics:
array<int>; for string-backed,array<string>.Examples:
Implementation Details
Engine changes (Zend):
Zend/zend_enum.stub.php: addBackedEnum::values()signature.Zend/zend_enum_arginfo.h: regenerated (committed) to includearginfo_class_BackedEnum_values.Zend/zend_string.h: addZEND_STR_VALUES("values").Zend/zend_enum.c:zend_enum_values_func(), mirroringcases()but extracting thevalueproperty of each case object.zend_enum_register_funcs()(user classes).Tests:
ext/reflection/tests/BackedEnum_values_reflection.phptext/reflection/tests/ReflectionEnum_toString_backed_int.phptext/reflection/tests/ReflectionEnum_toString_backed_string.phptZend/tests/enum/backed-values-int.phptZend/tests/enum/backed-values-string.phptZend/tests/enum/backed-values-empty.phptZend/tests/enum/backed-values-order.phptZend/tests/enum/backed-values-not-on-pure.phptZend/tests/enum/backed-values-ignore-regular-consts.phptDocumentation in-tree:
NEWS: announce the feature under Core.UPGRADING: list under “New Features”.Manual (php/doc-en) to be added in a separate PR:
values()signature, description, examples.values()alongsidecases()/from()/tryFrom().BackedEnum::values().Backward Compatibility
No BC break.
BackedEnum::values()only if the enum does not already declare a userland staticvalues()method.values(), that method is preserved and continues to work unchanged.values()method; either the native one or the user-defined one.values().Compatibility notes:
values()implementations is preserved; the engine does not override or redeclare them.Thanks, @vudaltsov, for highlighting the risks—resolved by conditional registration.
Optional Cleanup
Projects that wish to standardize on the native API can remove their custom
values()implementations and rely onBackedEnum::values(); behavior will remain the same.Mitigations Considered
values(); preserves BC while providing a standard API where missing.getValues(),valueList()): avoids collision but diverges from established conventions and symmetry withcases().Performance
Alternatives Considered
toArray(),getValues()): ambiguous or verbose;values()best matches existing community conventions and parallelscases().Prior Art
No previous RFCs proposing a
BackedEnum::values()method were found.A review of the PHP RFC index shows several enum-related proposals:
However, none of them address adding a convenience method returning the list of backing values.
This proposal introduces it for the first time.
Checklist
Thank you for reviewing!