rikudou/enums-trait

此包已被 废弃 并不再维护。未建议替代包。

用于在PHP中创建枚举的特质

v1.0.2 2019-12-03 14:01 UTC

This package is auto-updated.

Last update: 2021-08-31 11:57:15 UTC


README

这是另一个PHP枚举实现。

这个有什么不同呢?它使用特质,解决了我看到的其他实现都存在的问题——扩展某些基础枚举类。

所有枚举都返回相同的实例,因此您可以检查相等性(===),结果是真实的。

构造函数被设为私有,因此您不能通过new关键字直接构造实例(但您可以在类中创建一个构造函数并将其设为公共,如果您需要的话,但我建议不要这样做)。

每个内部方法都被设为私有,因此您不能扩展枚举(好吧,您可以,但那将没有意义)。

<?php

MyCoolEnum::Test() == MyCoolEnum::Test(); // true
MyCoolEnum::Test() === MyCoolEnum::Test(); // true
MyCoolEnum::Test() == MyCoolEnum::Test2(); // false
MyCoolEnum::Test() === MyCoolEnum::Test2(); // false

使用方法

创建枚举

<?php

use rikudou\PHPEnum\EnumTrait;

class MyCoolEnum
{
  use EnumTrait;
}

就是这样,您已经创建了一个枚举。这是一个相当基础的枚举,它通过魔术方法 __callStatic 支持几乎任何值。例如

<?php


$testValue = MyCoolEnum::TestValue();
$testValue2 = MyCoolEnum::TestValue2();
$testValue3 = MyCoolEnum::PrettyMuchAnythingCanGoHere();

如果您想使用IDE完成功能,您有两个选择

  1. 自己创建静态方法
  2. 为类添加phpdoc注释(例如PHPStorm支持它)

自己创建方法

<?php

use rikudou\PHPEnum\EnumTrait;

class MyCoolEnum
{
  use EnumTrait;
  
  public static function EnumValue1() {
    return static::_get("EnumValue1");
  }
  
  public static function EnumValue2() {
    return static::_get("EnumValue2");
  }
}

您的IDE现在将自动完成 EnumValue1EnumValue2 静态方法。

添加phpdoc注释

<?php

use rikudou\PHPEnum\EnumTrait;

/**
 * @method static static EnumValue1()
 * @method static static EnumValue2()
 */
class MyCoolEnum
{ 
  use EnumTrait;
}

对于IDE来说,结果与创建方法相同。

限制允许的枚举

如果您不喜欢通过魔术方法创建几乎任何枚举的想法,您可以像这样限制它们

<?php

use rikudou\PHPEnum\EnumTrait;

class MyCoolEnum
{
  use EnumTrait;
  
  private static function allowedValues()
  {
    return [
      "Value1",
      "Value2",
    ];
  }
  
  public static function Value3()
  {
    return static::_get("Value3");
  } 
}

现在您的枚举中只包含 只有 Value1Value2Value3。任何其他东西都会抛出 InvalidArgumentException

如您所见,allowedValues() 数组不关心您手动创建的方法。

使用枚举

<?php

function doSomething(MyCoolEnum $myCoolEnum)
{
  switch ($myCoolEnum) {
    case MyCoolEnum::Value1():
      return "Value1";
    case MyCoolEnum::Value2():
      return "Value2";
    // etc
  }
}

如您所见,您可以给枚举类型注解,PHP自己将检查它是否真的是枚举的实例。

然后您可以在switch、if/else或其他任何地方检查它们。

获取枚举值

如果您需要枚举持有的值,您可以使用 getValue() 方法。

构造的 __callStatic 魔术方法持有方法名的值

<?php

echo MyCoolEnum::SomeCoolValue()->getValue(); // echoes "SomeCoolValue"

您创建的方法有一个您给它们的值

<?php

use rikudou\PHPEnum\EnumTrait;

class MyCoolEnum {
  
  use EnumTrait;
  
  public static function MyCoolValue() {
    return static::_get(1);
  }
  
}

echo MyCoolEnum::MyCoolValue()->getValue(); // echoes 1

一些注意事项

  • 该特质根据值缓存对象,这意味着如果您创建了两个具有相同值的枚举值(静态方法),它们将返回相同的对象,例如,它们将在相等性测试中返回true
<?php

use rikudou\PHPEnum\EnumTrait;

class MyCoolEnum {
  
  use EnumTrait;
  
  public static function Value1() {
    return static::_get("Value");
  }
  
  public static function Value2() {
    return static::_get("Value"); // same as in Value1()
  }
  
}

var_dump(MyCoolEnum::Value1() === MyCoolEnum::Value2()); // dumps true
  • 如果您出于任何原因想要序列化枚举并将其存储(会话、数据库等),在反序列化后不会通过相等性测试,因此枚举不能被序列化,如果您尝试序列化它(使用魔术方法 __sleep__wakeup)将抛出 LogicException

好了,这就是全部内容。现在剩下的事情就是等待PHP端出现真正的枚举实现。