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

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

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


当前回答

上面的答案太棒了。但是,如果以两种不同的方式进行扩展,那么无论先进行哪种扩展,都会导致对函数的调用,从而创建缓存。这个缓存将被所有后续调用使用,无论调用是由哪个扩展发起的…

要解决这个问题,将变量和第一个函数替换为:

private static $constCacheArray = null;

private static function getConstants() {
    if (self::$constCacheArray === null) self::$constCacheArray = array();

    $calledClass = get_called_class();
    if (!array_key_exists($calledClass, self::$constCacheArray)) {
        $reflect = new \ReflectionClass($calledClass);
        self::$constCacheArray[$calledClass] = $reflect->getConstants();
    }

    return self::$constCacheArray[$calledClass];
}

其他回答

我在github上找到了这个库,我认为它提供了一个非常不错的答案。

PHP枚举实现灵感来自脾

你可以输入:function setAction(Action $ Action) { 你可以用方法丰富枚举(例如format, parse,…) 您可以扩展枚举以添加新值(将枚举设置为final以防止出现这种情况) 您可以得到所有可能值的列表(见下面)

宣言

<?php
use MyCLabs\Enum\Enum;

/**
 * Action enum
 */
class Action extends Enum
{
    const VIEW = 'view';
    const EDIT = 'edit';
}

使用

<?php
$action = new Action(Action::VIEW);

// or
$action = Action::VIEW();

类型提示枚举值:

<?php
function setAction(Action $action) {
    // ...
}

我试图用PHP创建一个枚举…这是非常有限的,因为它不支持对象作为枚举值,但仍然有点有用…

class ProtocolsEnum {

    const HTTP = '1';
    const HTTPS = '2';
    const FTP = '3';

    /**
     * Retrieve an enum value
     * @param string $name
     * @return string
     */
    public static function getValueByName($name) {
        return constant('self::'. $name);
    } 

    /**
     * Retrieve an enum key name
     * @param string $code
     * @return string
     */
    public static function getNameByValue($code) {
        foreach(get_class_constants() as $key => $val) {
            if($val == $code) {
                return $key;
            }
        }
    }

    /**
     * Retrieve associate array of all constants (used for creating droplist options)
     * @return multitype:
     */
    public static function toArray() {      
        return array_flip(self::get_class_constants());
    }

    private static function get_class_constants()
    {
        $reflect = new ReflectionClass(__CLASS__);
        return $reflect->getConstants();
    }
}

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

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());

我只是创建了一个库,希望它能完成这项工作。它可以在任何PHP项目中独立使用,并且有一些Laravel的好东西可以让生活变得更简单。我在生产项目中使用它们。

https://github.com/Kwaadpepper/enum

如果你喜欢或不喜欢,不要犹豫提供反馈。 它可以被打印出来,并序列化为JSON。它的定义很简单。

用法非常简单:

$enum = BasicEnum::someValue();
echo $enum->equals(BasicEnum::someValue()) ? 'true' : 'false'; // true
echo $enum->value; // 'someValue' or the value you have defined
echo $enum->label; // 'someValue' or the label you have defined
echo $enum; // 'someValue' or the value you have defined
echo json_encode($enum); // {"label": "someValue", "value: "someValue" }

枚举定义非常简单(值和标签方法是可选的)

/**
 * @method static self post()
 * @method static self about()
 * @method static self contact()
 */
class PostType extends BaseEnum
{
    protected static function values(): array
    {
        return [
            'post' => 0,
            'about' => 1,
            'contact' => 2
        ];
    }

    protected static function labels(): array
    {
        return [
            'post' => 'Regular posts',
            'about' => 'The about page',
            'contact' => 'The contact page'
        ];
    }
}

这可能很简单

enum DaysOfWeek {
    Sunday,
    Monday,
    // ...
}

在未来。

枚举类型