Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ PHP NEWS
initialization). (Arnaud)
. Enabled the TAILCALL VM on Windows when compiling with Clang >= 19 x86_64.
(henderkes)
. Added BackedEnum::values() method. (duiliofanton)

- BCMath:
. Added NUL-byte validation to BCMath functions. (jorgsowa)
Expand Down
65 changes: 65 additions & 0 deletions Zend/tests/enum/backed_enum_values.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--TEST--
BackedEnum::values() returns array of backing values
--FILE--
<?php

enum Status: string {
case ACTIVE = 'active';
case INACTIVE = 'inactive';
}

enum HttpStatus: int {
case OK = 200;
case NOT_FOUND = 404;
case SERVER_ERROR = 500;
}

enum UnitOnly {
case A;
case B;
}

// Test string-backed enum
echo "String-backed:\n";
var_dump(Status::values());

// Test int-backed enum
echo "Int-backed:\n";
var_dump(HttpStatus::values());

// Verify it replaces boilerplate array_column(Status::cases(), 'value')
echo "Equivalence with array_column:\n";
var_dump(Status::values() === array_column(Status::cases(), 'value'));
var_dump(HttpStatus::values() === array_column(HttpStatus::cases(), 'value'));

// Verify UnitEnum doesn't have values() method
echo "UnitEnum error:\n";
try {
UnitOnly::values();
} catch (Error $e) {
echo $e->getMessage() . "\n";
}

?>
--EXPECTF--
String-backed:
array(2) {
[0]=>
string(6) "active"
[1]=>
string(8) "inactive"
}
Int-backed:
array(3) {
[0]=>
int(200)
[1]=>
int(404)
[2]=>
int(500)
}
Equivalence with array_column:
bool(true)
bool(true)
UnitEnum error:
Call to undefined method UnitOnly::values()
35 changes: 35 additions & 0 deletions Zend/zend_enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,33 @@ static ZEND_NAMED_FUNCTION(zend_enum_cases_func)
} ZEND_HASH_FOREACH_END();
}

static ZEND_NAMED_FUNCTION(zend_enum_values_func)
{
zend_class_entry *ce = execute_data->func->common.scope;
zend_class_constant *c;

ZEND_PARSE_PARAMETERS_NONE();

array_init(return_value);

ZEND_HASH_MAP_FOREACH_PTR(CE_CONSTANTS_TABLE(ce), c) {
if (!(ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE)) {
continue;
}
zval *zv = &c->value;
if (Z_TYPE_P(zv) == IS_CONSTANT_AST) {
if (zval_update_constant_ex(zv, c->ce) == FAILURE) {
RETURN_THROWS();
}
}
zend_object *case_obj = Z_OBJ_P(zv);
zval *value_prop = zend_read_property_ex(case_obj->ce, case_obj, ZSTR_KNOWN(ZEND_STR_VALUE), 1, &EG(uninitialized_zval));
zval value_copy;
ZVAL_COPY(&value_copy, value_prop);
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &value_copy);
} ZEND_HASH_FOREACH_END();
}

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)
{
if (ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
Expand Down Expand Up @@ -479,6 +506,14 @@ void zend_enum_register_funcs(zend_class_entry *ce)
try_from_function->required_num_args = 1;
try_from_function->arg_info = zarginfo_class_BackedEnum_tryFrom + 1;
zend_enum_register_func(ce, ZEND_STR_TRYFROM_LOWERCASE, try_from_function);

zend_internal_function *values_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1);
values_function->handler = zend_enum_values_func;
values_function->function_name = ZSTR_KNOWN(ZEND_STR_VALUES);
values_function->fn_flags = fn_flags;
values_function->doc_comment = NULL;
values_function->arg_info = zarginfo_class_UnitEnum_cases + 1;
zend_enum_register_func(ce, ZEND_STR_VALUES, values_function);
}
}

Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_enum.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ interface BackedEnum extends UnitEnum
public static function from(int|string $value): static;

public static function tryFrom(int|string $value): ?static;

public static function values(): array;
}
5 changes: 4 additions & 1 deletion Zend/zend_enum_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Zend/zend_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ default: ZEND_UNREACHABLE();
_(ZEND_STR_SLEEP, "__sleep") \
_(ZEND_STR_WAKEUP, "__wakeup") \
_(ZEND_STR_CASES, "cases") \
_(ZEND_STR_VALUES, "values") \
_(ZEND_STR_FROM, "from") \
_(ZEND_STR_TRYFROM, "tryFrom") \
_(ZEND_STR_TRYFROM_LOWERCASE, "tryfrom") \
Expand Down
18 changes: 16 additions & 2 deletions ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
- Static properties [0] {
}

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

- Parameters [0] {
Expand All @@ -66,6 +66,13 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
}
- Return [ ?static ]
}

Method [ <internal, prototype BackedEnum> static public method values ] {

- Parameters [0] {
}
- Return [ array ]
}
}

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

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

- Parameters [0] {
Expand All @@ -122,6 +129,13 @@ Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
}
- Return [ ?static ]
}

Method [ <internal, prototype BackedEnum> static public method values ] {

- Parameters [0] {
}
- Return [ array ]
}
}

- Properties [2] {
Expand Down
18 changes: 16 additions & 2 deletions ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
- Static properties [0] {
}

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

- Parameters [0] {
Expand All @@ -66,6 +66,13 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
}
- Return [ ?static ]
}

Method [ <internal, prototype BackedEnum> static public method values ] {

- Parameters [0] {
}
- Return [ array ]
}
}

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

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

- Parameters [0] {
Expand All @@ -122,6 +129,13 @@ Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum
}
- Return [ ?static ]
}

Method [ <internal, prototype BackedEnum> static public method values ] {

- Parameters [0] {
}
- Return [ array ]
}
}

- Properties [2] {
Expand Down
Loading