我正在尝试从动态名称创建 php 8.1 枚举。看来不可能。所以给定一个枚举
enum Foo {
case bar;
}
以下当然有效:
Foo::bar
虽然这不起作用:
$name = "bar";
Foo::${$name}
这会导致:访问未声明的静态属性 App\Console\Commands\Foo::$bar
我在这里尝试了各种技巧,但没有成功。似乎不可能从动态名称获取枚举实例。我的自定义和快速解决方法如下所示,静态工厂:
/**
* @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");
}
我可以将其放入一个特征中,并在我的所有枚举中继承它,是的,问题解决了。
我的问题是:我在这里遗漏了什么吗?难道真的不能用本机 php 方法实例化枚举吗?还是我的想法错了?
php8.1 之前的 class-as-enum 编译器包曾经有这些方便的方法,请参阅 https://github.com/bensampo/laravel-enum 那么为什么这种非常常见的情况没有成为规范的一部分(只是好奇)?
最简单的方法是使用 constant() 函数:
<?php namespace App\Enums;
enum FooEnum: int
{
case FOO = 123;
case BAR = 456;
public static function fromName(string $name){
return constant("self::$name");
}
}
用途:
$name = "FOO";
dump(App\Enums\FooEnum::fromName($name));
/*
return
App\Enums\FooEnum {
+name: "FOO"
+value: 123
}
*/
你能做这样的事情吗?
enum Status {
case OK;
case DENIED;
}
$name = "OK";
$reflection = new \ReflectionEnum(Status::class);
if ( $reflection->hasConstant( $name ) ) {
var_dump($reflection->getConstant( $name ));
}
输出:
enum(Status::OK)
或者,您可以使枚举支持并使用
::from
方法。
// note: type-hinting required
enum Status: int
{
case OK = 200;
case ERROR = 500;
}
$statusValue = 200;
$status = Status::from($statusValue);
(returns Status::OK)
如果您使用 Laravel 转换,我相信它要求您无论如何使用支持的枚举。在您的模型中,您只需在模型上添加该演员
...
protected $casts = [
'status' => \App\Emums\Status::class,
];
单行:
$name = 'bar';
$enum = array_column(Foo::cases(), null, 'name')[$name] ?? null;
从 PHP 8.3 开始支持以下语法:
<?php
$enumName = 'Something';
SomeEnum::{$enumName};
SomeEnum::{$enumName}->value;
这适用于常量和枚举cases。它基本上是针对常量作为“动态类常量获取”完成的:https://www.php.net/releases/8.3/en.php#dynamic_class_constant_fetch,因为枚举基本上是作为具有特殊内容的类的特殊情况实现的(案例)-它也适用于他们。
您可以像使用常量一样使用
constant()
,但要注意 命名空间! 顺便说一句,这与 defined
和 const
定义相同的问题 - 即使在命名空间内,您必须在参考字符串中指定它!
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;