Hi,
I'm writing this email with a reference to https://wiki.php.net/rfc/howto.
My suggestion is that all enums (both basic/pure and backed) should
implement Stringable interface by default, and before you say that it's
totally wrong or impossible let me explain why.
Let's say I have a backed enum:
enum Suit: string {
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';}
Now if I'm trying something like this "echo Suit::Hearts;"I will get an
error "Fatal error: Uncaught Error: Object of class Suit could not be
converted to string"
BUT if I'm trying to use this enum as a part DTO (data transfer object) and
then serialize it or do something as simple as "echo
json_encode(Suit::Hearts);" then suddenly PHP knows how to convert enum to
string. This feels so unfair to me that I finally decided to write this
email.
The same applies to basic enums which have only case names, but they are
still stringable as $enum->name.
Please give me the initial feedback to understand if it's worth proceeding
with a RFC or not.
Best regards,
Janis Kajaks
My suggestion is that all enums (both basic/pure and backed) should
implement Stringable interface by default,
This has come up at least twice before:
These threads also touch on some of the same issues:
Fundamentally, there are different schools of thought on what an "enum"
should be, which lead to different sets of features.
I think some of those differences are fundamental enough that you could
only have both if the language had multiple enum-like things which the
user could choose between.
--
Rowan Tommins
[IMSoP]
My suggestion is that all enums (both basic/pure and backed) should
implement Stringable interface by default,This has come up at least twice before:
These threads also touch on some of the same issues:
Fundamentally, there are different schools of thought on what an "enum"
should be, which lead to different sets of features.I think some of those differences are fundamental enough that you could
only have both if the language had multiple enum-like things which the
user could choose between.
Also see: https://peakd.com/hive-168588/@crell/on-the-use-of-enums
Not auto-implementing Stringable was a deliberate design decision, for reasons that have not changed.
--Larry Garfield
So to summarize the proposed behavior (as I understand it):
- If an enum is backed, it auto-casts to ->value
- If an enum is not backed, it auto-casts to ->name
I believe this has the following problems (at least):
- Unbacked enums are not supposed to be representable as scalar values -
if I, as a developer, intended an enum to be representable as a scalar,
it would be backed; - Different behavior depending on whether the enum is backed or not is
confusing; - If an unbacked enum is created, then later a developer wants to change
it to backed, it can break code / change output in unexpected, and in
ways that are very difficult to search for. You need to, at least, not
just search for usages of the enum, but usages of the
properties/variables which can be that enum (and repeat recursively for
further assignments), then work out which of those might involve
auto-casting. (This sort of change probably isn't very common, but that
doesn't mean it should be made a nightmare when someone does want to do it)
I don't think enums should ever auto-cast to scalar values (backed or not)
Venturing further down this road starts getting into what I suspect is
dangerous territory, with obvious examples being:
- enums as array keys (which I would like to be able to do, but not via
this sort of auto-casting) - comparing different enums with the same backed values (or even
different unbacked enums with the same ->name)
And that's without looking at potential conflicts this behavior would
bring with planned features such as https://wiki.php.net/rfc/adts
My personal opinion on the current json_encode()
behavior with backed
enums here (and anywhere else where's there's similar auto-casting
behavior) is that it's undesirable and it should be an error. I think
it's completely ambiguous as to what the author intended (or if they
even intended to at all) when representing a backed enum in JSON.
If you do want this behavior in your application in cases such as
json_encode()
, it's pretty easy to write a wrapper or helper that casts
values as desired. I've done this with database level code (eg. casting
bool to 1/0 for MySQL, as a simple example).