27

I want to get the value of an Enum in PHP by its name. My enum is like:

enum Status : int
{
    case ACTIVE = 1;
    case REVIEWED = 2;
    // ...
}

Status::from(2) can be used to get "REVIEWED", but how can I resolve the value from the name stored in a string ?

2
  • suggested reading Commented Feb 5, 2022 at 21:56
  • Is it not simply echo Status::REVIEWED? - Sorry new to PHP Enums... Commented Feb 5, 2022 at 22:01

10 Answers 10

32

Well, it seems there is not any built-in solution in PHP. I've solve this with a custom function:

enum Status : int
{
    case ACTIVE = 1;
    case REVIEWED = 2;
    // ...

    public static function fromName(string $name): string
    {
        foreach (self::cases() as $status) {
            if( $name === $status->name ){
                return $status->value;
            }
        }
        throw new \ValueError("$name is not a valid backing value for enum " . self::class );
    }

}

Then, I simply use Status::fromName('ACTIVE') and get 1

If you want to mimic the from and tryFrom enum functions, you can also add:

public static function tryFromName(string $name): string|null
{
    try {
        return self::fromName($name);
    } catch (\ValueError $error) {
        return null;
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

keep in mind that from returns self, this function return string.
I'm confused why this is returning a string. It's turning a string into a string? Shouldn't it be returning a self somehow?
There's a built-in solution starting with PHP 8.3. See @fela's answer stackoverflow.com/a/73039918/8461337
27

Update for PHP8.3:

$name = 'REVIEWED';
Status::{$name}->value;
Status::{'REVIEWED')->value;

https://php.watch/versions/8.3/dynamic-class-const-enum-member-syntax-support

Previously:

You can use reflection for Backed case:

$reflection = new ReflectionEnumBackedCase(Status::class, 'REVIEWED');
$reflection->getBackingValue(); // 2
$reflection->getValue() // Status::REVIEWED if you need case object

Or enum reflection:

$reflection = new ReflectionEnum(Status::class);
$reflection->getCase('REVIEWED')->getValue()->value // 2

see also ReflectionEnumUnitCase

3 Comments

Reflection reduce performance of api
@Mitsukk I wonder where this belief comes from. Unless you mean PHP4 or less. In this particular case, Reflection is faster than the loop from the accepted answer, and the difference increases as the number of cases increases. Besides, performance was not mentioned in this question.
Thank's @fela, can you give me documentation about this please? My manager told me that, I want to have argument for discuss with him
17

The constant() function can return the value of a constant using a string variable.

This also applies to Enum class constants as mentioned in the basic enumeration section of the PHP Manual.

$name = 'REVIEWED';
$status = constant("Status::{$name}");

1 Comment

As the name of the enumeration is included in a string, this won't work well with many IDEs when you want to find all the places the quoted enumeration is used, or if you want to refactor the name of the enumeration.
6

You can also use the constant() function to get the Enum, then get the value from that. And personally, I would use a trait so you don't have to create the function for every enum you want this feature for:

trait EnumFromName
{
    public static function valueFromName(string $name): self
    {
        return constant("self::$name");
    }
}

Enum class:

enum Status : int
{
    use EnumFromName;

    case ACTIVE = 1;
    case REVIEWED = 2;
    // ...
}

Calling:

Status::valueFromName('REVIEWED')->value;

1 Comment

Awesome ! I think I'm in love again (with Traits, best feature of PHP 8).
5

You need to use tryFrom or from:

Example of enum:

enum Fruits: string
{
    case APPLE = 'Apple';
    case PEAR = 'Pear';
    case ORANGE = 'Orange';

    public function getDescription(): string
    {
        return match ($this) {
            Fruits::APPLE => 'X',
            Fruits::PEAR => 'Y',
            Fruits::ORANGE => 'Z',
        };
    }

}

tryFrom: Get Enum instance or null from string

Maps a scalar to an enum instance or null
$stringValue = 'Pear';

$fruit = Fruits::tryFrom($stringValue);

if ($fruit !== null) {
   echo $fruit->getDescription(); // "Y"
   echo $fruit->value; // "Pear"
}

Documentation: https://www.php.net/manual/en/backedenum.tryfrom.php

from: Get Enum instance or ValueError from string

Maps a scalar to an enum instance or throw a ValueError exception
$stringValue = 'Pear';

try { 
   $fruit = Fruits::from($stringValue);

   echo $fruit->getDescription(); // "Y"
   echo $fruit->value; // "Pear"
} catch (\ValueError $exception) { 
   echo $exception->getMessage(); // Fatal error: Uncaught ValueError: "Tree" is not a valid backing value for enum "Fruit"
}

Documentation: https://www.php.net/manual/en/backedenum.from.php

2 Comments

Since PHP 8.1.0 this is how it should be done.
This is incorrect, you haven't read the question properly. They are trying to get the Enum from the string value of the case name.
3

I use a custom method too, but I return an enum. The from method returns an enum, not a value. I think the fromName method should return an enum too. Then you have access to all methods of the enum. You don't need use another method - from.

public static function fromName(string $name): self
{
    foreach (self::cases() as $status) {
        if( $name === $status->name ){
            return $status;
        }
    }
    throw new \ValueError("$name is not a valid backing value for enum " . self::class );
}

public static function tryFromName(string $name): self|null
{
    try {
        return self::fromName($name);
    } catch (\ValueError $error) {
        return null;
    }
}

1 Comment

I am sorry, but how does it differ from?: stackoverflow.com/a/71002493/5113030
2

If anyone cares, I have created a library around that.

https://github.com/henzeb/enumhancer

Just add the trait to your enum

enum Status : int
{
    use Henzeb\Enumhancer\Enhancers;
    
    case ACTIVE = 1;
    case REVIEWED = 2;
    // ...
}

Status::get('ACTIVE');
Status::tryGet('ACTIVE');

You then don't have to use values at all. In that case you can also simply use from.

enum Status
{
    use Henzeb\Enumhancer\Enhancers;
    
    case ACTIVE;
    case REVIEWED;
    // ...
}

Status::from('ACTIVE')->key(); // returns 0
Status::tryFrom('Reviewed')->key(); // returns 1

It does so much more than that, but it defeats copying and pasting snippets around.

Comments

1

To get value from the name:

enum Status : int
{
   case ACTIVE = 1;
   case REVIEWED = 2;
   // ...
}

print(Status::REVIEWED->value);

Enum documentation

1 Comment

I have the name in a string, I edited my question to be more specific. Thanks for your answer!
0

This is what I did - https://3v4l.org/8R2fP#v8.2.10:

<?php

enum Gender
{
    case UNKNOWN;
    case MALE;
    case FEMALE;
}

/**
 * @template T as BackedEnum|UnitEnum
 * @param class-string<T> $enumClass
 * @param string $name
 * @return T|null
 */
function tryFromName(string $enumClass, string $name)
{
    $constName = $enumClass . '::' . $name;

    return is_subclass_of($enumClass, UnitEnum::class) && defined($constName)
        ? constant($constName)
        : null;
}

// enum(Gender::UNKNOWN)
var_dump(tryFromName(Gender::class, 'UNKNOWN'));

// enum(Gender::MALE)
var_dump(tryFromName(Gender::class, 'MALE'));

// enum(Gender::FEMALE)
var_dump(tryFromName(Gender::class, 'FEMALE'));

// NULL
var_dump(tryFromName(Gender::class, 'null'));

1 Comment

Hello, please don't post code only and add an explantation as to why you think that this is the optimal solution. People are supposed to learn from your answer, which might not occur if they just copy paste code without knowing why it should be used.
0

Update at 31/05/2025

This can be achived with Backed enumerations ¶:


<?php

enum Suit: string
{
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';
}

Then you can do:

$record = 'C';
$suit =  Suit::from($record);
// Invalid data throws a ValueError: "X" is not a valid scalar value for enum "Suit"
print $suit->value;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.