Reputation: 3907
I'm looking at enum in PHP 8.1. I have a string variable gathered from a database record, and I want to select the correct enum value case based on that string. For example:
enum Test: string {
case FOO = 'baz';
case BAR = 'buz';
}
I can select the first of those using the string value of the case:
$x = 'baz';
$y = Test::from($x);
// $y is now `Test::FOO`.
But what about the other way around? What if $x = "FOO"
? How do I select the enum case from "FOO"?
Hard-coded, it would be Test::FOO
, but I don't know the syntax for using a variable. I've tried a few things like Test::{$x}
but the enum syntax doesn't seem to like variables very much.
The standard example all the tutorials give seems a perfect use case for this usage, but none of them mention it.
enum Suit: string {
case Clubs = '♣';
case Diamonds = '♦';
case Hearts = '♥';
case Spades = '♠';
}
I can totally imagine needing to get ♣
from "Clubs". I can't imagine ever needing the reverse.
Upvotes: 0
Views: 1082
Reputation: 55427
To me, storing the name of the constant and not the value defeats the purpose of a backed enum. But, reading through many of the discussions on enums, many people were against backed enums and/or stringified enums in general, so I won't argue the point except to say that I would consider it the same as storing Clubs
for a class constant such as:
class Suit
{
const Clubs = '♣';
const Diamonds = '♦';
const Hearts = '♥';
const Spades = '♠';
}
To your question, yes you can get the enum back by using the constant
function (as noted in this thread):
enum Suit: string {
case Clubs = '♣';
case Diamonds = '♦';
case Hearts = '♥';
case Spades = '♠';
}
$cardString = 'Clubs';
$cardEnumFQString = Suit::class . '::' . $cardString;
$cardEnum = constant($cardEnumFQString);
echo $cardEnum->value;
Demo here: https://3v4l.org/WTrIv#v8.1.10
Personally, when I use backed enums it is for database, URL transport or similar, and I use the value. If I want to expose anything user-facing I more often than not just add a custom attribute and I have a common utility function that parses that.
EDIT Here's some helper code that shows a trait I use to reflect on enum attributes: https://3v4l.org/QKBvU#v8.1.10. It might seem like overkill for some people, but for some objects I like to keep their meta information attached to the object instead of a separate render file.
EDIT: Enums vs Class Constants
This is not a definitive answer to the question in any way, I want to make that clear. There is definitely a lot more that I'm not covering and I'd encourage a read-through on the original discussion as well as the follow-up discussion and the over-arching ADTs RFC. There's a lot in those discussions, pros, cons, WTFs, alternatives, "I don't get it", etc.
One of the major differences between an enum and a class constant is that an enum is a first-class object in PHP and as such it can have methods, whereas a class constant is limited to scalars, scalar expressions and arrays (ignoring recent post-enum changes). This means you can pass an object that holds a specific value around, and have that object include methods. The PHP documentation has a great example for the color
method on Suit
.
You could define your constants in one file and include a utility class with methods like getColor(string $colorName)
however there's no way to limit the choices that get passed to it, nor can you guard against someone using a literal instead of your constant.
Can you do that with pure classes? Absolutely, and many of us used libraries such as https://github.com/myclabs/php-enum or https://github.com/spatie/enum to do that. This just unifies it at the language level.
I definitely agree that it can be a grey area. I came from a .Net background originally so I've had enums for a very long time, and even wrote a "why enums vs static class members" over a decade ago, so for me I've had a long time to play with them, and was very excited when they came to PHP. The best I can tell you is that you might just have to play with them to see if they fit. I'm very certain that some long-time PHP people won't use enums ever because they've solved this problem in the past in other ways, and I think that's okay, too.
Upvotes: 2