我想通过名字在PHP中获取枚举的值。 我的枚举如下:
enum Status : int
{
case ACTIVE = 1;
case REVIEWED = 2;
// ...
}
Status::from(2)
可以用来获取 "REVIEWED"
,但是如何从存储在字符串中的名称解析出值呢?
好的,似乎在PHP中没有任何内置的解决方案。我用一个自定义函数来解决这个问题:
enum Status : int
{
case ACTIVE = 1;
case REVIEWED = 2;
// ...
public static function fromName(string $name): string
{
foreach (self::cases() as $status) {
if( $name === $status->name ){
return $status->value;
}
}
throw new \ValueError("$name is not a valid backing value for enum " . self::class );
}
}
那么,我只需使用 Status::fromName('ACTIVE')
就能得到 1
如果要模仿枚举函数中的from
和tryFrom
,也可以添加:
public static function tryFromName(string $name): string|null
{
try {
return self::fromName($name);
} catch (\ValueError $error) {
return null;
}
}
from
返回 self
,而此函数返回 string
。 - shamaseen您可以使用反射来处理后端情况:
$reflection = new ReflectionEnumBackedCase(Status::class, 'REVIEWED');
$reflection->getBackingValue(); // 2
$reflection->getValue() // Status::REVIEWED if you need case object
或枚举反射:
$reflection = new ReflectionEnum(Status::class);
$reflection->getCase('REVIEWED')->getValue()->value // 2
请参阅ReflectionEnumUnitCase。
$name = 'REVIEWED';
$status = constant("Status::{$name}");
我也使用自定义方法,但是我返回一个枚举类型。
from 方法返回一个枚举类型,而不是一个值。我认为 fromName 方法也应该返回一个枚举类型。这样你就可以访问枚举的所有方法了。你不需要再使用另一个方法 - from。
public static function fromName(string $name): self
{
foreach (self::cases() as $status) {
if( $name === $status->name ){
return $status;
}
}
throw new \ValueError("$name is not a valid backing value for enum " . self::class );
}
public static function tryFromName(string $name): self|null
{
try {
return self::fromName($name);
} catch (\ValueError $error) {
return null;
}
}
如果有人在意,我已经围绕它创建了一个库。
https://github.com/henzeb/enumhancer
只需将特征添加到您的枚举中
enum Status : int
{
use Henzeb\Enumhancer\Enhancers;
case ACTIVE = 1;
case REVIEWED = 2;
// ...
}
Status::get('ACTIVE');
Status::tryGet('ACTIVE');
那么你就不必使用任何值了。在这种情况下,你也可以简单地使用 from。
enum Status
{
use Henzeb\Enumhancer\Enhancers;
case ACTIVE;
case REVIEWED;
// ...
}
Status::from('ACTIVE')->key(); // returns 0
Status::tryFrom('Reviewed')->key(); // returns 1
它能做的远不止这些,但可以避免复制和粘贴代码片段。
获取名称的值:
enum Status : int
{
case ACTIVE = 1;
case REVIEWED = 2;
// ...
}
print(Status::REVIEWED->value);
trait EnumFromName
{
public static function valueFromName(string $name): self
{
return constant("self::$name");
}
}
enum Status : int
{
use EnumFromName;
case ACTIVE = 1;
case REVIEWED = 2;
// ...
}
呼叫:
Status::valueFromName('REVIEWED')->value;
tryFrom
或from
:
enum Fruits: string
{
case APPLE = 'Apple';
case PEAR = 'Pear';
case ORANGE = 'Orange';
public function getDescription(): string
{
return match ($this) {
Fruits::APPLE => 'X',
Fruits::PEAR => 'Y',
Fruits::ORANGE => 'Z',
};
}
}
tryFrom
: 从字符串获取枚举实例或null$stringValue = 'Pear';
$fruit = Fruits::tryFrom($stringValue);
if ($fruit !== null) {
echo $fruit->getDescription(); // "Z"
echo $fruit->value; // "Pear"
}
文档: https://www.php.net/manual/zh/backedenum.tryfrom.php
from
: 通过字符串获取枚举实例或抛出ValueError
异常ValueError
异常$stringValue = 'Pear';
try {
$fruit = Fruits::from($stringValue);
echo $fruit->getDescription(); // "Z"
echo $fruit->value; // "Pear"
} catch (\ValueError $exception) {
echo $exception->getMessage(); // Fatal error: Uncaught ValueError: "X" is not a valid backing value for enum "Fruit"
}
<?php
enum Gender
{
case UNKNOWN;
case MALE;
case FEMALE;
}
/**
* @template T as BackedEnum|UnitEnum
* @param class-string<T> $enumClass
* @param string $name
* @return T|null
*/
function tryFromName(string $enumClass, string $name)
{
$constName = $enumClass . '::' . $name;
return is_subclass_of($enumClass, UnitEnum::class) && defined($constName)
? constant($constName)
: null;
}
// enum(Gender::UNKNOWN)
var_dump(tryFromName(Gender::class, 'UNKNOWN'));
// enum(Gender::MALE)
var_dump(tryFromName(Gender::class, 'MALE'));
// enum(Gender::FEMALE)
var_dump(tryFromName(Gender::class, 'FEMALE'));
// NULL
var_dump(tryFromName(Gender::class, 'null'));
Status::REVIEWED
吗?- 抱歉我对 PHP 中的 Enums 不熟悉… - Simon K