我知道PHP还没有本地枚举。但是我已经习惯了来自Java世界的它们。我喜欢使用枚举来提供ide的自动补全功能能够理解的预定义值。

常量可以解决这个问题,但是存在名称空间冲突问题,而且(实际上是因为)它们是全局的。数组没有名称空间的问题,但是它们太模糊了,它们可以在运行时被覆盖,而且ide很少知道如何在没有额外的静态分析注释或属性的情况下自动填充它们的键。

你有什么常用的解决方案/变通办法吗?有人记得PHP的人对枚举有什么想法或决定吗?


当前回答

一个不使用反射的更简单、更轻的版本:

abstract class enum {
    private function __construct() {}
    static function has($const) {
        $name = get_called_class();
        return defined("$name::$const");
    }
    static function value($const) {
        $name = get_called_class();
        return defined("$name::$const")? constant("$name::$const") : false;
    }
}

用法:

class requestFormat  extends enum { const HTML = 1; const JSON = 2; const XML  = 3; const FORM = 4; }

echo requestFormat::value('JSON'); // 2
echo requestFormat::has('JSON');   // true

这提供了常量的优势,也允许检查它们的有效性,但它缺乏更复杂的解决方案所提供的其他花哨功能,更明显的是无法检查值的反向(在上面的例子中,你不能检查'2'是否是一个有效值)

其他回答

对于简单的枚举,我使用如下结构。通常,您可以将它们用于switch语句。

<?php 
  define("OPTION_1", "1");
  define("OPTION_2", OPTION_1 + 1);
  define("OPTION_3", OPTION_2 + 1);

  // Some function...
   switch($Val){
    case OPTION_1:{ Perform_1();}break;
    case OPTION_2:{ Perform_2();}break;
    ...
  }
?>

它不像c++中的本地枚举那样方便,但如果你以后想在两者之间添加一个选项,它似乎可以工作,并且需要更少的维护。

我使用带有常量的类:

class Enum {
    const NAME       = 'aaaa';
    const SOME_VALUE = 'bbbb';
}

print Enum::NAME;

类常量呢?

<?php

class YourClass
{
    const SOME_CONSTANT = 1;

    public function echoConstant()
    {
        echo self::SOME_CONSTANT;
    }
}

echo YourClass::SOME_CONSTANT;

$c = new YourClass;
$c->echoConstant();

如果你想要类型安全和一堆与该类型匹配的常量,一种方法是为你的枚举创建一个抽象类,然后用一个锁定的构造函数扩展这个类,如下所示:

abstract class DaysOfWeekEnum{
    public function __construct(string $value){
        $this->value = $value; 
    }
    public function __toString(){
        return $this->value;
    }

}
class Monday extends DaysOfWeekEnum{
    public function __construct(){
        parent::__construct("Monday");
    }
}

class Tuesday extends DaysOfWeekEnum{
    public function __construct(){
        parent::__construct("Tuesday");
    }
}

然后你可以让你的方法获取DaysOfWeek的一个实例,并传递给它一个Monday、Tuesday等实例……唯一的缺点是每次你想使用你的枚举时都必须“更新”一个实例,但我发现这是值得的。

function printWeekDay(DaysOfWeek $day){
    echo "Today is $day.";
}

printWeekDay(new Monday());

这是我对“动态”enum的看法…这样我就可以用变量来调用它,比如从表单中。

看看这个代码块下面的更新版本…

$value = "concert";
$Enumvalue = EnumCategory::enum($value);
//$EnumValue = 1

class EnumCategory{
    const concert = 1;
    const festival = 2;
    const sport = 3;
    const nightlife = 4;
    const theatre = 5;
    const musical = 6;
    const cinema = 7;
    const charity = 8;
    const museum = 9;
    const other = 10;

    public function enum($string){
        return constant('EnumCategory::'.$string);
    }
}

更新:更好的方式做…

class EnumCategory {

    static $concert = 1;
    static $festival = 2;
    static $sport = 3;
    static $nightlife = 4;
    static $theatre = 5;
    static $musical = 6;
    static $cinema = 7;
    static $charity = 8;
    static $museum = 9;
    static $other = 10;

}

电话

EnumCategory::${$category};