如何在PHP中获取枚举类型的所有值?

51

PHP 8.1即将发布,支持枚举。 我正在测试一些枚举功能,但找不到太多关于它的文档。 因此我的问题是:如何获取枚举的所有值?

8个回答

119

对于基本枚举:

$suits = array_column(Suit::cases(), 'name');

对于需要返回值的支持枚举类型:

$suits = array_column(Suit::cases(), 'value');
你可以像这样做:

然后你可以像这样做:

trait EnumToArray
{

  public static function names(): array
  {
    return array_column(self::cases(), 'name');
  }

  public static function values(): array
  {
    return array_column(self::cases(), 'value');
  }

  public static function array(): array
  {
    return array_combine(self::values(), self::names());
  }

}

enum Suit: string
{

  use EnumToArray;

  case Hearts = 'H';
  case Diamonds = 'D';
  case Clubs = 'C';
  case Spades = 'S';

}

Suit::array() 将返回:

Array
(
    [H] => Hearts
    [D] => Diamonds
    [C] => Clubs
    [S] => Spades
)

3
谢谢。我使用了 array_combine(self::names(), self::values())。将名称作为数组键更符合我的直觉。 - Maksida
谢谢,我添加了一个containsValue()函数,返回\in_array($value, self::values(), true); - undefined
1
@v.nivuahc 你可以直接使用tryFrom来实现这个功能:https://www.php.net/manual/en/backedenum.tryfrom.php - undefined

39

经过一些研究,我找到了答案。你可以使用静态方法:cases()

enum Status
{
    case PAID;
    case Cancelled;
}

Status::cases();

cases方法将返回一个数组,其中包含每个值的枚举(UnitEnum接口)。


您可以在以下链接中了解有关 PHP 8.1 枚举方法的信息:https://php.watch/versions/8.1/enums#enum-use-cases - timnavigate

6

需要值而不是枚举实例吗?

我为此编写了一个 Composer 包 othyn/php-enum-enhancements,因为 UnitEnum::cases() 方法并不是我想要的,该方法返回一个 MySuperCoolEnum 实例的数组,而不是它们底层的原始类型值,这正是我想要的。

这是一个可以轻松添加到任何枚举中的 trait,它执行以下操作:

  • 添加一个新的静态方法 UnitEnum::valueArray(): array,将 Enum 中的所有值作为同类型的数组 Enum 值返回

  • 添加一个新的静态方法 UnitEnum::valueList(string $separator = ', '): string,将 Enum 中的所有值作为逗号分隔的列表字符串返回

对于常规 枚举,它将产生以下结果:

<?php

namespace App\Enums;

use Othyn\PhpEnumEnhancements\Traits\EnumEnhancements;

enum TestEnum
{
    use EnumEnhancements;

    case Alpha;
    case Bravo;
    case Charlie;
    case Delta;
    case Echo;
}

var_dump(TestEnum::valueArray());

// Results in the following being printed:
// array(5) {
//   [0]=>
//   string(5) "Alpha"
//   [1]=>
//   string(5) "Bravo"
//   [2]=>
//   string(7) "Charlie"
//   [3]=>
//   string(5) "Delta"
//   [4]=>
//   string(4) "Echo"
// }

var_dump(TestEnum::valueList());

// Results in the following being printed:
// string(34) "Alpha, Bravo, Charlie, Delta, Echo"

var_dump(TestEnum::valueList(separator: ':'));

// Results in the following being printed:
// string(30) "Alpha:Bravo:Charlie:Delta:Echo"

...而对于后备枚举,以下是一个string示例:

<?php

namespace App\Enums;

use Othyn\PhpEnumEnhancements\Traits\EnumEnhancements;

enum TestStringBackedEnum: string
{
    use EnumEnhancements;

    case Alpha   = 'alpha';
    case Bravo   = 'bravo';
    case Charlie = 'charlie';
    case Delta   = 'delta';
    case Echo    = 'echo';
}

var_dump(TestStringBackedEnum::valueArray());

// Results in the following being printed:
// array(5) {
//   [0]=>
//   string(5) "alpha"
//   [1]=>
//   string(5) "bravo"
//   [2]=>
//   string(7) "charlie"
//   [3]=>
//   string(5) "delta"
//   [4]=>
//   string(4) "echo"
// }

var_dump(TestStringBackedEnum::valueList());

// Results in the following being printed:
// string(34) "alpha, bravo, charlie, delta, echo"

var_dump(TestStringBackedEnum::valueList(separator: ':'));

// Results in the following being printed:
// string(30) "alpha:bravo:charlie:delta:echo"

...而且它也适用于int

在软件包的README的使用部分中有更多示例。


5
除了使用 UnitEnum::cases() 外,您还可以使用 ReflectionEnum
$reflection = new ReflectionEnum(Status::class);

$reflection->getCases();

请注意,无论哪种情况,您都无法获取枚举方法。但只要 ReflectionEnum 扩展了 ReflectionClass,您就可以使用其余的 ReflectionClass 方法,例如 getMethods

这比被接受的答案好多了。我更喜欢在处理类、接口、枚举等方面使用“反射”。 - Rotimi
2
这种做法比仅使用 Status::cases() 更好吗? - nickdnk

3

在我的项目中,我使用了以下内容:

public static function toAssociativeArray(): array
{
    foreach(self::cases() as $case) {
        $array[$case->value] = $case->name;
    }
    return $array;
}

这将导致一个类似于这样的关联数组; 使用字符串作为值。
enum DiaryRole: string
{
    case DANGER  = 'red';
    case WARNING = 'yellow';
    case SAFE    = 'green';
}

$array = [
    'red'    => 'DANGER',
    'yellow' => 'WARNING',
    'green'  => 'SAFE'
];

当使用整数作为值时

enum DiaryRole: int
{
    case DANGER  = 1;
    case WARNING = 2;
    case SAFE    = 3;
}

$array = [
    1 => 'DANGER',
    2 => 'WARNING',
    3 => 'SAFE'
];

您现在可以使用该数组获取任何所需信息,您可以使用array_keys()array_values()函数来获取列或值。

我已经使用此代码轻松地在表单选择器中遍历它们。


2
我认为最好的选择是使用trait来实现。
例如: EnumsToArray.php
<?php

namespace App\Traits;

trait EnumsToArray {
    public static function toArray(): array {
        return array_map(
            fn(self $enum) => $enum->value, 
            self::cases()
        );
    }
}

后来,在您的枚举中,您应该有:

use App\Traits\EnumsToArray;

Enum Currency: string {
    use EnumsToArray;
    
    case DOLLAR = "usd";
    case EURO = "eur";
}

1

我将@Michael稍作修改的方法封装成一个小包,因为我需要在多个项目中使用:

https://github.com/laracraft-tech/laravel-useful-traits#usefulenums

通过 Composer 安装:

composer require laracraft-tech/laravel-useful-traits

它是这样工作的:

use LaracraftTech\LaravelUsefulTraits\UsefulEnums;

enum PaymentType: int
{
    use UsefulEnums;

    case Pending = 1;
    case Failed = 2;
    case Success = 3;
}

PaymentType::names();   // return ['Pending', 'Failed', 'Success']
PaymentType::values();  // return [1, 2, 3]
PaymentType::array();   // return ['Pending' => 1, 'Failed' => 2, 'Success' => 3]

0

通过以下方法获得枚举值的另一种方式:


<?php namespace JCKCon\Enums;

enum UsersPermissions: string
{
    case CREATE = "create";
    case UPDATE = "update";
    case DELETE = "delete";
    case VIEW = "view";
    case PUBLISH = "publish";

    public static function toArray()
    {
        $values = [];

        foreach (self::cases() as $props) {
            array_push($values, $props->value);
        }

        return $values;
    }
}


dd(UsersPermissions::toArray());

/**
array:5 [
  0 => "create"
  1 => "update"
  2 => "delete"
  3 => "view"
  4 => "publish"
]
**/

value在此情况下不是一个已定义的属性。您应该使用$props->name。另外,我会将toArray方法重写为:return array_map(fn($case) => $case->name, self::cases()); - Cornel Raiu
忽略这部分内容:“在这种情况下,value不是一个定义的属性。你应该使用$props->name。”我没有注意到它是一个后端枚举类型。糟糕! - Cornel Raiu
好的,太棒了!你可以投票支持这个回答来帮助其他人。 - ObiTech Invents

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接