Skip to content

Commit cd54810

Browse files
committed
Add BackedEnum::values() method to retrieve backing values as an array
1 parent 0078a27 commit cd54810

7 files changed

Lines changed: 139 additions & 5 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
--TEST--
2+
BackedEnum::values() returns array of backing values
3+
--FILE--
4+
<?php
5+
6+
enum Status: string {
7+
case ACTIVE = 'active';
8+
case INACTIVE = 'inactive';
9+
}
10+
11+
enum HttpStatus: int {
12+
case OK = 200;
13+
case NOT_FOUND = 404;
14+
case SERVER_ERROR = 500;
15+
}
16+
17+
enum UnitOnly {
18+
case A;
19+
case B;
20+
}
21+
22+
// Test string-backed enum
23+
echo "String-backed:\n";
24+
var_dump(Status::values());
25+
26+
// Test int-backed enum
27+
echo "Int-backed:\n";
28+
var_dump(HttpStatus::values());
29+
30+
// Verify it replaces boilerplate array_column(Status::cases(), 'value')
31+
echo "Equivalence with array_column:\n";
32+
var_dump(Status::values() === array_column(Status::cases(), 'value'));
33+
var_dump(HttpStatus::values() === array_column(HttpStatus::cases(), 'value'));
34+
35+
// Verify UnitEnum doesn't have values() method
36+
echo "UnitEnum error:\n";
37+
try {
38+
UnitOnly::values();
39+
} catch (Error $e) {
40+
echo $e->getMessage() . "\n";
41+
}
42+
43+
?>
44+
--EXPECTF--
45+
String-backed:
46+
array(2) {
47+
[0]=>
48+
string(6) "active"
49+
[1]=>
50+
string(8) "inactive"
51+
}
52+
Int-backed:
53+
array(3) {
54+
[0]=>
55+
int(200)
56+
[1]=>
57+
int(404)
58+
[2]=>
59+
int(500)
60+
}
61+
Equivalence with array_column:
62+
bool(true)
63+
bool(true)
64+
UnitEnum error:
65+
Call to undefined method UnitOnly::values()

Zend/zend_enum.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,33 @@ static ZEND_NAMED_FUNCTION(zend_enum_cases_func)
297297
} ZEND_HASH_FOREACH_END();
298298
}
299299

300+
static ZEND_NAMED_FUNCTION(zend_enum_values_func)
301+
{
302+
zend_class_entry *ce = execute_data->func->common.scope;
303+
zend_class_constant *c;
304+
305+
ZEND_PARSE_PARAMETERS_NONE();
306+
307+
array_init(return_value);
308+
309+
ZEND_HASH_MAP_FOREACH_PTR(CE_CONSTANTS_TABLE(ce), c) {
310+
if (!(ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE)) {
311+
continue;
312+
}
313+
zval *zv = &c->value;
314+
if (Z_TYPE_P(zv) == IS_CONSTANT_AST) {
315+
if (zval_update_constant_ex(zv, c->ce) == FAILURE) {
316+
RETURN_THROWS();
317+
}
318+
}
319+
zend_object *case_obj = Z_OBJ_P(zv);
320+
zval *value_prop = zend_read_property_ex(case_obj->ce, case_obj, ZSTR_KNOWN(ZEND_STR_VALUE), 1, &EG(uninitialized_zval));
321+
zval value_copy;
322+
ZVAL_COPY(&value_copy, value_prop);
323+
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &value_copy);
324+
} ZEND_HASH_FOREACH_END();
325+
}
326+
300327
ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_class_entry *ce, zend_long long_key, zend_string *string_key, bool try_from)
301328
{
302329
if (ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
@@ -479,6 +506,14 @@ void zend_enum_register_funcs(zend_class_entry *ce)
479506
try_from_function->required_num_args = 1;
480507
try_from_function->arg_info = zarginfo_class_BackedEnum_tryFrom + 1;
481508
zend_enum_register_func(ce, ZEND_STR_TRYFROM_LOWERCASE, try_from_function);
509+
510+
zend_internal_function *values_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1);
511+
values_function->handler = zend_enum_values_func;
512+
values_function->function_name = ZSTR_KNOWN(ZEND_STR_VALUES);
513+
values_function->fn_flags = fn_flags;
514+
values_function->doc_comment = NULL;
515+
values_function->arg_info = zarginfo_class_UnitEnum_cases + 1;
516+
zend_enum_register_func(ce, ZEND_STR_VALUES, values_function);
482517
}
483518
}
484519

Zend/zend_enum.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ interface BackedEnum extends UnitEnum
1212
public static function from(int|string $value): static;
1313

1414
public static function tryFrom(int|string $value): ?static;
15+
16+
public static function values(): array;
1517
}

Zend/zend_enum_arginfo.h

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ default: ZEND_UNREACHABLE();
639639
_(ZEND_STR_SLEEP, "__sleep") \
640640
_(ZEND_STR_WAKEUP, "__wakeup") \
641641
_(ZEND_STR_CASES, "cases") \
642+
_(ZEND_STR_VALUES, "values") \
642643
_(ZEND_STR_FROM, "from") \
643644
_(ZEND_STR_TRYFROM, "tryFrom") \
644645
_(ZEND_STR_TRYFROM_LOWERCASE, "tryfrom") \

ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
4343
- Static properties [0] {
4444
}
4545

46-
- Static methods [3] {
46+
- Static methods [4] {
4747
Method [ <internal, prototype UnitEnum> static public method cases ] {
4848

4949
- Parameters [0] {
@@ -66,6 +66,13 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
6666
}
6767
- Return [ ?static ]
6868
}
69+
70+
Method [ <internal, prototype BackedEnum> static public method values ] {
71+
72+
- Parameters [0] {
73+
}
74+
- Return [ array ]
75+
}
6976
}
7077

7178
- Properties [2] {
@@ -99,7 +106,7 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
99106
- Static properties [0] {
100107
}
101108

102-
- Static methods [3] {
109+
- Static methods [4] {
103110
Method [ <internal, prototype UnitEnum> static public method cases ] {
104111

105112
- Parameters [0] {
@@ -122,6 +129,13 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
122129
}
123130
- Return [ ?static ]
124131
}
132+
133+
Method [ <internal, prototype BackedEnum> static public method values ] {
134+
135+
- Parameters [0] {
136+
}
137+
- Return [ array ]
138+
}
125139
}
126140

127141
- Properties [2] {

ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
4343
- Static properties [0] {
4444
}
4545

46-
- Static methods [3] {
46+
- Static methods [4] {
4747
Method [ <internal, prototype UnitEnum> static public method cases ] {
4848

4949
- Parameters [0] {
@@ -66,6 +66,13 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
6666
}
6767
- Return [ ?static ]
6868
}
69+
70+
Method [ <internal, prototype BackedEnum> static public method values ] {
71+
72+
- Parameters [0] {
73+
}
74+
- Return [ array ]
75+
}
6976
}
7077

7178
- Properties [2] {
@@ -99,7 +106,7 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
99106
- Static properties [0] {
100107
}
101108

102-
- Static methods [3] {
109+
- Static methods [4] {
103110
Method [ <internal, prototype UnitEnum> static public method cases ] {
104111

105112
- Parameters [0] {
@@ -122,6 +129,13 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
122129
}
123130
- Return [ ?static ]
124131
}
132+
133+
Method [ <internal, prototype BackedEnum> static public method values ] {
134+
135+
- Parameters [0] {
136+
}
137+
- Return [ array ]
138+
}
125139
}
126140

127141
- Properties [2] {

0 commit comments

Comments
 (0)