I´m trying to create an php 8.1 enum from a dynamic name. Seems not to be possible. So given an enum
enum Foo {
case bar;
}
The following works of course: Foo::bar While this doesn´t:
$name = "bar";
Foo::${$name}
This results in: Access to undeclared static property App\Console\Commands\Foo::$bar
I tried various tricks here, to no avail. It seems not to be possible to get an enum instance from a dynamic name. My custom and quick workaround looks like this, a static factory:
/**
* @throws \Exception
*/
public static function fromName(string $name) : self {
foreach(Foo::cases() as $enum){
if($enum->name === $name){
return $enum;
}
}
throw new \Exception("Not a valid enum name");
}
I could put this in a trait and inherit this in all my enums, yes, problem solved.
My question is: am I missing something here? Is it really not possible to instantiate an enum with native php methods? Or am I thinking in the wrong direction?
The pre php8.1 class-as-enum composer packages used to have those convenience methods, see https://github.com/bensampo/laravel-enum So why is this pretty common case not part of the specification (just curious)?
The most simple way for that is using the constant() function:
<?php namespace App\Enums;
enum FooEnum: int
{
case FOO = 123;
case BAR = 456;
public static function fromName(string $name){
return constant("self::$name");
}
}
Usage:
$name = "FOO";
dump(App\Enums\FooEnum::fromName($name));
/*
return
App\Enums\FooEnum {
+name: "FOO"
+value: 123
}
*/
Following syntax is supported since PHP 8.3:
<?php
$enumName = 'Something';
SomeEnum::{$enumName};
SomeEnum::{$enumName}->value;
This works for both constants and enum cases. It was basically done for constants as "dynamic class constant fetch": https://www.php.net/releases/8.3/en.php#dynamic_class_constant_fetch as since enums are basically implemented as a special case of class with special contants (cases) - it works for them too.
You can use constant() as you would use for a constant, but be aware of namespaces! by the way this is the same issue as with defined & const definition - even when inside the namespace, you have to specify it in the reference string!
namespace SomeNamespace;
enum MyEnum: int {
case SomeName = 42;
}
$name ='SomeName';
echo constant("SomeNamespace\MyEnum::$name")->value;
enum MyEnum: int {
case SomeName = 42;
}
$name ='SomeName';
echo constant("\MyEnum::$name")->value;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With