Skip to content

Home CN

yinfuyuan edited this page Jan 5, 2021 · 8 revisions

PHP 枚举

PHPEnum是为PHP开发人员准备的枚举类库,它由基础类 Enum 和拓展类 PhpEnum 构成。 其中基础类完全参考了 Java枚举 并实现和其相似的功能。 而拓展类是通过结合PHP的语言特性实现了一些快速访问的方法。

如果您正在使用旧版本,你可以通过下面的链接找到正确的文档

基础类Enum

基础类完全参考了Java枚举,如果你之前了解Java枚举,那么在这里你可以以相同的方式使用它。

在Java中定义的枚举常量格式为构造参数的调用,在无参数时括号和构造方法可以省略,在有参数时,必须提供和参数格式相对应的构造方法。

例:

// 无参数时括号和构造方法可以省略
public enum Color {
    RED, GREEN, BLUE;
}

// 有参数时必须要提供正确的构造方法
public enum Color {
    RED("FF0000"), GREEN("00FF00"), BLUE("0000FF");

    Color(String hexadecimal) {
    }
}

但在PHP中,PHP的语法并不允许我们这样做,所以PhpEnum使用常量数组来表示构造方法中的参数,在无参时构造方法可以省略但参数数组不可省略,在有参数时,必须提供和参数格式相对应的构造方法。

PhpEnum中的构造方法名称为construct且必须使用protected来修饰

例:

// 无参数时构造方法可以省略,但参数数组必须为空数组
class Color extends \PhpEnum\Enum
{
    const RED = [];
    const GREEN = [];
    const BLUE = [];
}

// 有参数时必须要提供正确的构造方法
class Color extends \PhpEnum\Enum
{
    const RED = ["FF0000"];
    const GREEN = ["00FF00"];
    const BLUE = ["0000FF"];

    protected function construct(string $hexadecimal)
    {
    }
}

在实际使用中,我们通常需要对参数定义与其对应的属性和属性的getter使其可以对外访问

例:

class Color extends \PhpEnum\Enum
{
    const RED = ["FF0000"];
    const GREEN = ["00FF00"];
    const BLUE = ["0000FF"];

    private string $hexadecimal;

    protected function construct(string $hexadecimal)
    {
        $this->hexadecimal = $hexadecimal;
    }

    public function getHexadecimal(): string
    {
        return $this->hexadecimal;
    }
}

基础类为我们提供了如下方法

  • name:string 返回枚举的名称
  • ordinal:int 返回枚举定义的序,从0开始
  • equals:bool 与另一枚举对比是否相等
  • static values:static[] 返回所有枚举实例,正确的使用参数prefix可以减少内存开销,也可以在存在相同枚举值时返回正确的结果,虽然不建议在同一个枚举中定义相同值
  • static valueOf:static 根据枚举名称返回枚举实例

拓展类PhpEnum

拓展类是基础类的子类,所以它与基础类的定义和使用方式完全相同,拓展类提供了更多方法来使用枚举。 拓展类提供的方法大多数与枚举属性相关,所以在使用拓展类时应正确定义属性以及属性的getter。

例:

class Color extends \PhpEnum\PhpEnum
{
    const RED = ["FF0000"];
    const GREEN = ["00FF00"];
    const BLUE = ["0000FF"];

    private string $hexadecimal;

    protected function construct(string $hexadecimal)
    {
        $this->hexadecimal = $hexadecimal;
    }

    public function getHexadecimal(): string
    {
        return $this->hexadecimal;
    }
}

拓展类为我们提供了如下方法

  • get:mixed 获取一个属性值。注意这个方法并不能代替属性的getter,相反当你的属性使用private修饰时,你应该提供属性的getter以保证此方法的正确性,这是其他方法的基础(虽然通过反射也可以获取属性的值,但那样会带来很大的内存开销)
  • enumNameEquals:bool 判断枚举的名称和指定的名称是否相等
  • propertyEquals:bool 判断枚举的属性值和指定的属性值是否相等,注意当属性的类型是浮点类型时,会优先使用bccomp函数进行对比,你需要通过重写scale方法来设置正确的小数位数,设置全局生效
  • static containsEnumName:bool 判断枚举名称中是否包含指定的枚举名称
  • static containsProperty:int 返回枚举属性值等于指定值的枚举数量
  • static ofProperty:static 返回枚举属性值等于指定值的枚举实例,当找到的枚举数量大于1时,会抛出一个异常
  • static properties:array 返回所有枚举的某个属性值的数组
  • static names:string[] 返回所有的枚举名称
  • static count:int 返回所有枚举的数量

拓展类对equalscontainsof提供了魔术方法触发的方式,也就是在方法中包含关键字和属性名称时,会自动找到正确的方法调用。

例:

var_dump(Color::RED()->hexadecimalEquals('FF0000')); // bool(true)
var_dump(Color::containsHexadecimal('FF0000')); // int(1)
var_dump(Color::ofHexadecimal('FF0000')); // object(Color)
Clone this wiki locally