[RFC] [Discussion] Stringable Enums

php.internals

Daniel Scherzer

271 days ago
Hi internals, I'd like to start the discussion for a new RFC about removing the prohibition on `__toString()` methods on enums. * RFC: https://wiki.php.net/rfc/stringable-enums * Implementation: https://github.com/php/php-src/pull/20415 Thanks, -Daniel

Rowan Tommins [IMSoP]

271 days ago
On 4 December 2025 04:50:57 GMT, Daniel Scherzer <daniel.e.scherzer@gmail.com> wrote:
>Hi internals, > >I'd like to start the discussion for a new RFC about removing the >prohibition on `__toString()` methods on enums. > >* RFC: https://wiki.php.net/rfc/stringable-enums >* Implementation: https://github.com/php/php-src/pull/20415
My first instinct was that this was dragging up a discussion we've had lots of times, but your examples make clear that you are *not* just talking about converting enums to their backing value. On the other hand, that does make me wonder: in what way is (string)$foo clearer than $foo->toString() for those use cases? In my experience, it just makes the functionality less discoverable - people don't think to try (string)$exception or (string)$simpleXmlNode, so miss that those have specific behaviour. And is it even a good name for those methods? In the date-time package, for instance, it would be better named toEnglishName() or getFullEnglishName(), as its docblock explicitly says. In the framework code, it seems to be used for a property called $displayValue, so the obvious name for the method would be getDisplayValue(). Regards, Rowan Tommins [IMSoP]

Tim Düsterhus

271 days ago
Hi Am 2025-12-04 09:01, schrieb Rowan Tommins [IMSoP]:
> My first instinct was that this was dragging up a discussion we've had > lots of times, but your examples make clear that you are *not* just > talking about converting enums to their backing value. > > On the other hand, that does make me wonder: in what way is > (string)$foo clearer than $foo->toString() for those use cases? In my > experience, it just makes the functionality less discoverable - people > don't think to try (string)$exception or (string)$simpleXmlNode, so > miss that those have specific behaviour. > > And is it even a good name for those methods? In the date-time package, > for instance, it would be better named toEnglishName() or > getFullEnglishName(), as its docblock explicitly says. In the framework > code, it seems to be used for a property called $displayValue, so the > obvious name for the method would be getDisplayValue().
I fundamentally disagree with the proposal for reasons similar to those that Rowan mentioned. More specifically, I consider implementing `__toString()` to be a mistake, unless it is for a debug representation. There rarely is a single (or primary), obvious and parameter-less string representation for a given object. There might be one for enums, since they can't hold state, but as the previous RFCs indicated, folks generally expect it to just be the enum's value which then just encourages folks to treat enums as “fancy strings” or “fancy class constants” rather a proper data type unto itself even more than they already do, where it's `->value` all the time. And with the planned enhancements of enums into full tagged unions, I'd also rather not make decisions now that we might regret later when actually extending enums to tagged unions. Best regards Tim Düsterhus

Derick Rethans

271 days ago
On Thu, 4 Dec 2025, Tim Düsterhus wrote:
> Hi > > Am 2025-12-04 09:01, schrieb Rowan Tommins [IMSoP]: > > > And is it even a good name for those methods? In the date-time > > package, for instance, it would be better named toEnglishName() or > > getFullEnglishName(), as its docblock explicitly says. In the > > framework code, it seems to be used for a property called > > $displayValue, so the obvious name for the method would be > > getDisplayValue(). > > I fundamentally disagree with the proposal for reasons similar to those that > Rowan mentioned. More specifically, I consider implementing `__toString()` to > be a mistake, unless it is for a debug representation.
I agree, and also: We usually have a `__debugInfo()` method for debugging purposes. Instead of allowing `__toString()` to be added, I think I would rather see `__debugInfo()` being allowed. It must continue to be not possible to treat enums as strings. cheers, Derick

Bob Weinand

270 days ago
Good point Derick, On 4.12.2025 14:36:14, Derick Rethans wrote:
> On Thu, 4 Dec 2025, Tim Düsterhus wrote: > >> Hi >> >> Am 2025-12-04 09:01, schrieb Rowan Tommins [IMSoP]: >> >>> And is it even a good name for those methods? In the date-time >>> package, for instance, it would be better named toEnglishName() or >>> getFullEnglishName(), as its docblock explicitly says. In the >>> framework code, it seems to be used for a property called >>> $displayValue, so the obvious name for the method would be >>> getDisplayValue(). >> I fundamentally disagree with the proposal for reasons similar to those that >> Rowan mentioned. More specifically, I consider implementing `__toString()` to >> be a mistake, unless it is for a debug representation. > I agree, and also: > > We usually have a `__debugInfo()` method for debugging purposes. Instead > of allowing `__toString()` to be added, I think I would rather see > `__debugInfo()` being allowed. > > It must continue to be not possible to treat enums as strings. > > cheers, > Derick
Daniel, if you want to improve the magic method situation here, I'd much rather encourage you to add __debugInfo() than anything else. (Also fwiw I think __toString() should never have existed in the first place; but that's a wholly different topic.) Bob

Larry Garfield

270 days ago
On Thu, Dec 4, 2025, at 2:44 PM, Bob Weinand wrote:
> Good point Derick, > > On 4.12.2025 14:36:14, Derick Rethans wrote: >> On Thu, 4 Dec 2025, Tim Düsterhus wrote: >> >>> Hi >>> >>> Am 2025-12-04 09:01, schrieb Rowan Tommins [IMSoP]: >>> >>>> And is it even a good name for those methods? In the date-time >>>> package, for instance, it would be better named toEnglishName() or >>>> getFullEnglishName(), as its docblock explicitly says. In the >>>> framework code, it seems to be used for a property called >>>> $displayValue, so the obvious name for the method would be >>>> getDisplayValue(). >>> I fundamentally disagree with the proposal for reasons similar to those that >>> Rowan mentioned. More specifically, I consider implementing `__toString()` to >>> be a mistake, unless it is for a debug representation. >> I agree, and also: >> >> We usually have a `__debugInfo()` method for debugging purposes. Instead >> of allowing `__toString()` to be added, I think I would rather see >> `__debugInfo()` being allowed. >> >> It must continue to be not possible to treat enums as strings. >> >> cheers, >> Derick > > > Daniel, if you want to improve the magic method situation here, I'd much > rather encourage you to add __debugInfo() than anything else. > > (Also fwiw I think __toString() should never have existed in the first > place; but that's a wholly different topic.) > > > Bob
I've long argued against allowing __toString() for reasons others have already covered, so I won't bother repeating it. But off hand I don't see why __debugInfo() would cause a problem. I am not sure it's useful before ADTs happen, but I don't think it would cause any harm? --Larry Garfield

Bob Weinand

270 days ago
Hey Larry, On 5.12.2025 01:21:43, Larry Garfield wrote:
> I've long argued against allowing __toString() for reasons others have already covered, so I won't bother repeating it. But off hand I don't see why __debugInfo() would cause a problem. I am not sure it's useful before ADTs happen, but I don't think it would cause any harm?
I found to semi-commonly (the ergonomics of querying are bad) add attributes to enum cases. A __debugInfo() handler could provide information about all attached metadata. Bob

Rokas Šleinius

270 days ago
On Fri, Dec 5, 2025, 02:42 Bob Weinand <bobwei9@hotmail.com> wrote:
> > Hey Larry, > > On 5.12.2025 01:21:43, Larry Garfield wrote: > > I've long argued against allowing __toString() for reasons others have already covered, so I won't bother repeating it. But off hand I don't see why __debugInfo() would cause a problem. I am not sure it's useful before ADTs happen, but I don't think it would cause any harm? > > I found to semi-commonly (the ergonomics of querying are bad) add attributes to enum cases. A __debugInfo() handler could provide information about all attached metadata. > > > Bob
Slight correction: not metadata, we already have it in the form of the entire internal object state. It's full of noise, the user rarely wants that. __debugInfo() could contain a user-readable representation of the important parts of an object. For example dumping a Carbon object: Illuminate\Support\Carbon 2025-12-05 09:38:17.634246 Europe/Berlin (+01:00) vs Illuminate\Support\Carbon @1764923897 {#304 #endOfTime: false #startOfTime: false #constructedObjectId: "00000000000001300000000000000000" #localMonthsOverflow: null #localYearsOverflow: null #localStrictModeEnabled: null #localHumanDiffOptions: null #localToStringFormat: null #localSerializer: null #localMacros: null #localGenericMacros: null #localFormatFunction: null #localTranslator: null #dumpProperties: array:3 [ 0 => "date" 1 => "timezone_type" 2 => "timezone" ] #dumpLocale: null #dumpDateProperties: null }

Larry Garfield

270 days ago
On Thu, Dec 4, 2025, at 6:32 PM, Bob Weinand wrote:
> Hey Larry, > > On 5.12.2025 01:21:43, Larry Garfield wrote: >> I've long argued against allowing __toString() for reasons others have already covered, so I won't bother repeating it. But off hand I don't see why __debugInfo() would cause a problem. I am not sure it's useful before ADTs happen, but I don't think it would cause any harm? > I found to semi-commonly (the ergonomics of querying are bad) add > attributes to enum cases. A __debugInfo() handler could provide > information about all attached metadata. > > > Bob
Ah, interesting case. OK, color me unopposed to allowing __debugInfo(), but still opposed to __toString(). --Larry Garfield