From 7809a952b19ab4455da080af2894c830ebef7ceb Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 7 Nov 2025 10:05:47 -0800 Subject: [PATCH] [RFC] Allow `__toString()` on enums https://wiki.php.net/rfc/stringable-enums --- Zend/tests/enum/__toString.phpt | 16 ---------- .../enum/toString/backed_enum_value.phpt | 18 ++++++++++++ Zend/tests/enum/toString/magic_interface.phpt | 29 +++++++++++++++++++ Zend/tests/enum/toString/magic_method.phpt | 18 ++++++++++++ .../tests/enum/toString/param_validation.phpt | 18 ++++++++++++ .../enum/toString/return_validation.phpt | 18 ++++++++++++ .../enum/toString/visibility_validation.phpt | 20 +++++++++++++ Zend/zend_enum.c | 3 +- 8 files changed, 122 insertions(+), 18 deletions(-) delete mode 100644 Zend/tests/enum/__toString.phpt create mode 100644 Zend/tests/enum/toString/backed_enum_value.phpt create mode 100644 Zend/tests/enum/toString/magic_interface.phpt create mode 100644 Zend/tests/enum/toString/magic_method.phpt create mode 100644 Zend/tests/enum/toString/param_validation.phpt create mode 100644 Zend/tests/enum/toString/return_validation.phpt create mode 100644 Zend/tests/enum/toString/visibility_validation.phpt diff --git a/Zend/tests/enum/__toString.phpt b/Zend/tests/enum/__toString.phpt deleted file mode 100644 index 9407e482fb727..0000000000000 --- a/Zend/tests/enum/__toString.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Enum __toString ---FILE-- -name; - } -} - -?> ---EXPECTF-- -Fatal error: Enum Foo cannot include magic method __toString in %s on line %d diff --git a/Zend/tests/enum/toString/backed_enum_value.phpt b/Zend/tests/enum/toString/backed_enum_value.phpt new file mode 100644 index 0000000000000..c800f3e1a847c --- /dev/null +++ b/Zend/tests/enum/toString/backed_enum_value.phpt @@ -0,0 +1,18 @@ +--TEST-- +Enum with __toString() magic method - backed enum value accessible +--FILE-- +name . ' = ' . $this->value; + } +} + +echo Foo::Bar; + +?> +--EXPECT-- +Foo::Bar = Baz diff --git a/Zend/tests/enum/toString/magic_interface.phpt b/Zend/tests/enum/toString/magic_interface.phpt new file mode 100644 index 0000000000000..65d19549cf094 --- /dev/null +++ b/Zend/tests/enum/toString/magic_interface.phpt @@ -0,0 +1,29 @@ +--TEST-- +Enum with __toString() magic method - Stringable interface added +--FILE-- +name . ' is a case of the ' . __CLASS__ . ' enum'; + } +} + +function printStringable(Stringable $s) { + echo $s; +} + +var_dump(class_implements(Foo::class)); +printStringable(Foo::Bar); + +?> +--EXPECT-- +array(2) { + ["UnitEnum"]=> + string(8) "UnitEnum" + ["Stringable"]=> + string(10) "Stringable" +} +Bar is a case of the Foo enum diff --git a/Zend/tests/enum/toString/magic_method.phpt b/Zend/tests/enum/toString/magic_method.phpt new file mode 100644 index 0000000000000..3a2f355fc9b11 --- /dev/null +++ b/Zend/tests/enum/toString/magic_method.phpt @@ -0,0 +1,18 @@ +--TEST-- +Enum supports __toString() magic method +--FILE-- +name . ' is a case of the ' . __CLASS__ . ' enum'; + } +} + +echo Foo::Bar; + +?> +--EXPECT-- +Bar is a case of the Foo enum diff --git a/Zend/tests/enum/toString/param_validation.phpt b/Zend/tests/enum/toString/param_validation.phpt new file mode 100644 index 0000000000000..a0768249ee4ce --- /dev/null +++ b/Zend/tests/enum/toString/param_validation.phpt @@ -0,0 +1,18 @@ +--TEST-- +Enum with __toString() magic method - param validation +--FILE-- + +--EXPECTF-- +Fatal error: Method Foo::__toString() cannot take arguments in %s on line %d diff --git a/Zend/tests/enum/toString/return_validation.phpt b/Zend/tests/enum/toString/return_validation.phpt new file mode 100644 index 0000000000000..483ccde0ea420 --- /dev/null +++ b/Zend/tests/enum/toString/return_validation.phpt @@ -0,0 +1,18 @@ +--TEST-- +Enum with __toString() magic method - return validation +--FILE-- + +--EXPECTF-- +Fatal error: Foo::__toString(): Return type must be string when declared in %s on line %d diff --git a/Zend/tests/enum/toString/visibility_validation.phpt b/Zend/tests/enum/toString/visibility_validation.phpt new file mode 100644 index 0000000000000..5d6c025086e6e --- /dev/null +++ b/Zend/tests/enum/toString/visibility_validation.phpt @@ -0,0 +1,20 @@ +--TEST-- +Enum with __toString() magic method - visibility validation +--FILE-- + +--EXPECTF-- +Warning: The magic method Foo::__toString() must have public visibility in %s on line %d + +Fatal error: Access level to Foo::__toString() must be public (as in class Stringable) in %s on line %d diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index ae9e7b701213f..0788175d6a9ee 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -80,7 +80,7 @@ static void zend_verify_enum_properties(const zend_class_entry *ce) static void zend_verify_enum_magic_methods(const zend_class_entry *ce) { - // Only __get, __call and __invoke are allowed + // Only __get, __call, __toString, and __invoke are allowed ZEND_ENUM_DISALLOW_MAGIC_METHOD(constructor, "__construct"); ZEND_ENUM_DISALLOW_MAGIC_METHOD(destructor, "__destruct"); @@ -89,7 +89,6 @@ static void zend_verify_enum_magic_methods(const zend_class_entry *ce) ZEND_ENUM_DISALLOW_MAGIC_METHOD(__set, "__set"); ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unset, "__unset"); ZEND_ENUM_DISALLOW_MAGIC_METHOD(__isset, "__isset"); - ZEND_ENUM_DISALLOW_MAGIC_METHOD(__tostring, "__toString"); ZEND_ENUM_DISALLOW_MAGIC_METHOD(__debugInfo, "__debugInfo"); ZEND_ENUM_DISALLOW_MAGIC_METHOD(__serialize, "__serialize"); ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unserialize, "__unserialize");