从动态名称获取 PHP 枚举

问题描述 投票:0回答:5

我正在尝试从动态名称创建 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 那么为什么这种非常常见的情况没有成为规范的一部分(只是好奇)?

php enums php-8.1
5个回答
12
投票

最简单的方法是使用 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
}
*/

3
投票

你能做这样的事情吗?


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)


1
投票

或者,您可以使枚举支持并使用

::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,
];

1
投票

单行:

$name = 'bar';
$enum = array_column(Foo::cases(), null, 'name')[$name] ?? null;

0
投票

PHP 8.3+

从 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,因为枚举基本上是作为具有特殊内容的类的特殊情况实现的(案例)-它也适用于他们。

PHP 8.1 和 8.2

您可以像使用常量一样使用

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;
© www.soinside.com 2019 - 2024. All rights reserved.