PHP: Select enum case from string value of case name

Viewed 20

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.

1 Answers

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 genera, 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.

Related