Skip to content

Commit 58cee12

Browse files
[RFC] Allow __debugInfo() on enums
https://wiki.php.net/rfc/debugable-enums
1 parent fa5ab4f commit 58cee12

File tree

9 files changed

+123
-23
lines changed

9 files changed

+123
-23
lines changed

Zend/tests/enum/__debugInfo.phpt

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Enum with __debugInfo() magic method - backed enum value accessible
3+
--FILE--
4+
<?php
5+
6+
enum Foo: string {
7+
case Bar = "Baz";
8+
9+
public function __debugInfo() {
10+
return [__CLASS__ . '::' . $this->name . ' = ' . $this->value];
11+
}
12+
}
13+
14+
var_dump(Foo::Bar);
15+
16+
?>
17+
--EXPECT--
18+
enum(Foo::Bar) (1) {
19+
[0]=>
20+
string(14) "Foo::Bar = Baz"
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Enum supports __debugInfo() magic method
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __debugInfo() {
10+
return [$this->name . ' is a case of the ' . __CLASS__ . ' enum'];
11+
}
12+
}
13+
14+
var_dump(Foo::Bar);
15+
16+
?>
17+
--EXPECT--
18+
enum(Foo::Bar) (1) {
19+
[0]=>
20+
string(29) "Bar is a case of the Foo enum"
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
When an enum does not have __debugInfo() it is printed nicely
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
}
9+
10+
var_dump(Foo::Bar);
11+
12+
?>
13+
--EXPECT--
14+
enum(Foo::Bar)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Enum with __debugInfo() magic method - param validation
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __debugInfo(mixed $arg): array {
10+
return [];
11+
}
12+
}
13+
14+
var_dump(Foo::Bar);
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Method Foo::__debugInfo() cannot take arguments in %s on line %d
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Enum with __debugInfo() magic method - return validation
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __debugInfo(): int {
10+
return 5;
11+
}
12+
}
13+
14+
var_dump(Foo::Bar);
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Foo::__debugInfo(): Return type must be ?array when declared in %s on line %d
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Enum with __debugInfo() magic method - visibility validation
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
private function __debugInfo(): array {
10+
return [];
11+
}
12+
}
13+
14+
var_dump(Foo::Bar);
15+
16+
?>
17+
--EXPECTF--
18+
Warning: The magic method Foo::__debugInfo() must have public visibility in %s on line %d
19+
enum(Foo::Bar) (0) {
20+
}

Zend/zend_enum.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static void zend_verify_enum_properties(const zend_class_entry *ce)
9090

9191
static void zend_verify_enum_magic_methods(const zend_class_entry *ce)
9292
{
93-
// Only __get, __call and __invoke are allowed
93+
// Only __get, __call, __debugInfo and __invoke are allowed
9494

9595
ZEND_ENUM_DISALLOW_MAGIC_METHOD(constructor, "__construct");
9696
ZEND_ENUM_DISALLOW_MAGIC_METHOD(destructor, "__destruct");
@@ -100,7 +100,6 @@ static void zend_verify_enum_magic_methods(const zend_class_entry *ce)
100100
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unset, "__unset");
101101
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__isset, "__isset");
102102
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__tostring, "__toString");
103-
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__debugInfo, "__debugInfo");
104103
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__serialize, "__serialize");
105104
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unserialize, "__unserialize");
106105

ext/standard/var.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */
166166
break;
167167
case IS_OBJECT: {
168168
zend_class_entry *ce = Z_OBJCE_P(struc);
169-
if (ce->ce_flags & ZEND_ACC_ENUM) {
169+
if (ce->ce_flags & ZEND_ACC_ENUM && ce->__debugInfo == NULL) {
170170
zval *case_name_zval = zend_enum_fetch_case_name(Z_OBJ_P(struc));
171171
php_printf("%senum(%s::%s)\n", COMMON, ZSTR_VAL(ce->name), Z_STRVAL_P(case_name_zval));
172172
return;
@@ -180,11 +180,16 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */
180180
ZEND_GUARD_OR_GC_PROTECT_RECURSION(guard, DEBUG, zobj);
181181

182182
myht = zend_get_properties_for(struc, ZEND_PROP_PURPOSE_DEBUG);
183-
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
184-
const char *prefix = php_var_dump_object_prefix(Z_OBJ_P(struc));
183+
if (ce->ce_flags & ZEND_ACC_ENUM) {
184+
zval *case_name_zval = zend_enum_fetch_case_name(Z_OBJ_P(struc));
185+
php_printf("%senum(%s::%s) (%d) {\n", COMMON, ZSTR_VAL(ce->name), Z_STRVAL_P(case_name_zval), myht ? zend_array_count(myht) : 0);
186+
} else {
187+
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
188+
const char *prefix = php_var_dump_object_prefix(Z_OBJ_P(struc));
185189

186-
php_printf("%s%sobject(%s)#%d (%d) {\n", COMMON, prefix, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0);
187-
zend_string_release_ex(class_name, 0);
190+
php_printf("%s%sobject(%s)#%d (%d) {\n", COMMON, prefix, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0);
191+
zend_string_release_ex(class_name, 0);
192+
}
188193

189194
if (myht) {
190195
zend_ulong num;

0 commit comments

Comments
 (0)