Reputation: 73
I search for a simple solution to get the case of an enum by a string. There are BackedEnums. For example:
<?php
enum Status: string
{
case OK = "OK";
case FAILED = "FAILED";
...
}
$status = Status::tryFrom("OK"); // or from("OK");
But I don't want to write the same word twice for getting that result. Is there a native way to get the case without having BackedEnums? I want something like:
<?php
enum Status
{
case OK;
case FAILED;
...
}
$status = Status::get("OK"); //returns Status::OK;
Or do I need to write my own funcionality for that? For example:
enum Status
{
case OK;
case FAILED;
public static function get(string $name): null|Status
{
$name = strtoupper(trim($name));
if(empty($name))
return null;
foreach(Status::cases() as $status)
{
if($status->name == $name)
return $status;
}
return null;
}
}
Status::get("OK"); // -> Status::OK
Is there a better way to achieve the same?
Upvotes: 7
Views: 13712
Reputation: 3565
Only a BackedEnum
has the from
and tryFrom
methods available sadly, but they can easily be polyfilled, here is how you could write your own from
and tryFrom
in a trait for reusability
<?php
trait LazyEnum
{
public static function tryFrom($caseName): ?self
{
$rc = new ReflectionEnum(self::class);
return $rc->hasCase($caseName) ? $rc->getConstant($caseName) : null;
}
/**
* @throws Exception
*/
public static function from($caseName): self
{
return self::tryFrom($caseName) ?? throw new Exception('Enum '. $caseName . ' not found in ' . self::class);
}
}
enum Test
{
use LazyEnum;
case FOO;
case BAR;
}
var_dump(Test::tryFrom('FOO')); //enum(Test::FOO)
var_dump(Test::tryFrom('BAZ')); //NULL
Upvotes: 3
Reputation: 1002
Instead of writing your own, you could use https://packagist.org/packages/henzeb/enumhancer
This will do for you what you need, and so much more.
Upvotes: 0
Reputation: 74
ReflectionEnum
is the answer. In the rfc for enums in php8.1 is a chapter Reflection
There you have the method getCase(string $name)
and in combination with getValue()
you get the enum. With that function you can get the case via a string value.
Your Example would look like this:
$status = (new ReflectionEnum("Status"))->getCase("OK")->getValue();
Best used with an ExceptionHandler since the transmitted string, if not found, could end up in a ReflectionException
Upvotes: 5
Reputation: 877
There is an internal name getter like this.
Status::OK->name;
This will return Ok
Status::OK->value;
This will return the value
To get the case from the value. Use this
$case = Status::tryFrom('Ok')
https://www.php.net/manual/en/backedenum.tryfrom.php
Upvotes: 10