【问题标题】:Check if PHP enum contains case, like try() method on basic (not backed) enumerations检查 PHP 枚举是否包含大小写,例如基本(非支持)枚举的 try() 方法
【发布时间】:2022-07-08 02:03:06
【问题描述】:

我有基本的枚举

enum Fruit
{
  case APPLE;
  case ORANGE;
  case BANANA;
}

还有一些使用枚举类型的函数:

function eatFruit (Fruit $fruit)
{
  // do stuff
}

和内容未知的变量

$fruit = $_POST['fruit']; // user choosed "MILK"
if (?????) { // how to check if it's fruit?
  eatFruit($fruit); // this should not be executed
}

我在documentation 中找不到检查枚举是否包含特定大小写的简单方法。

这样的支持枚举是可能的

enum Fruit
{
  case APPLE = 'APPLE';
  case ORANGE = 'ORANGE';
  case BANANA = 'BANANA';
}

Fruit::from('');
Fruit::tryFrom('');

这可行,但from 在我的第一个示例中不存在于非支持枚举上。

Fatal error: Uncaught Error: Call to undefined method Fruit::from()

【问题讨论】:

标签: php enums php-8.1


【解决方案1】:

您可以为此使用静态方法cases()。这将返回枚举中所有值的数组。这些值有一个“名称”属性,它是您可以检查的字符串表示形式(支持的枚举也有一个“值”属性,其中包含您在枚举中定义的字符串值)。

所以一个示例实现可能是这样的:

enum Fruit {
    case APPLE;
    case ORANGE;
    case BANANA;
}

// String from user input
$fruit = $_POST['fruit'];

// Find matching fruit in all enum cases
$fruits = Fruit::cases();
$matchingFruitIndex = array_search($fruit, array_column($fruits, "name"));

// If found, eat it
if ($matchingFruitIndex !== false) {
    $matchingFruit = $fruits[$matchingFruitIndex];
    eatFruit($matchingFruit);
} else {
    echo $fruit . " is not a valid Fruit";
}

function eatFruit(Fruit $fruit): void {
    if ($fruit === Fruit::APPLE) {
        echo "An apple a day keeps the doctor away";
    } elseif ($fruit === Fruit::ORANGE) {
        echo "When life gives you oranges, make orange juice";
    } elseif ($fruit === Fruit::BANANA) {
        echo "Banana for scale";
    }
}

带有示例数据的工作版本:https://3v4l.org/ObD3s

如果您想更频繁地使用不同的枚举来执行此操作,您可以为此编写一个辅助函数:

function getEnumValue($value, $enumClass) {
    $cases = $enumClass::cases();
    $index = array_search($value, array_column($cases, "name"));
    if ($index !== false) {
        return $cases[$index];
    }
    
    return null;
}

$fruit = getEnumValue($_POST['fruit'], Fruit::class);
if ($fruit !== null) {
    eatFruit($fruit);
} else {
    echo $_POST['fruit'] . " is not a valid Fruit";
}

具有相同样本数据的示例:https://3v4l.org/bL8Wa

【讨论】:

    【解决方案2】:

    如果您需要 from 或 tryFrom,请使用 https://packagist.org/packages/henzeb/enumhancer。它会为您提供这些以及更多。

    【讨论】:

      【解决方案3】:
      $fruitFromPost = current(array_filter(
          Fruit::cases(),
          fn(Fruit $fruitCase) => $fruitCase->name === $_POST['fruit']
      )) ?: Fruit::APPLE;
      

      我们过滤Fruit::cases 对每个案例进行匿名调用,我们检查案例名称是否相同,如 POST 中提供的那样。然后我们从过滤中得到current 值,如果它是假的(在名称中找不到),我们将 APPLE 指定为默认值(或者你可以保持为假或 null,如你所愿)。请注意,它区分大小写。

      【讨论】:

        猜你喜欢
        • 2012-12-03
        • 2011-03-10
        • 1970-01-01
        • 1970-01-01
        • 2012-08-30
        • 2021-01-16
        • 1970-01-01
        • 2021-09-25
        • 1970-01-01
        相关资源
        最近更新 更多