PHP 上的枚举 [英] Enumerations on PHP

查看:23
本文介绍了PHP 上的枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 PHP 还没有原生枚举.但是我已经习惯了 Java 世界中的它们.我很乐意使用枚举来提供 IDE 的自动完成功能可以理解的预定义值.

I know that PHP doesn't yet have native Enumerations. But I have become accustomed to them from the Java world. I would love to use enums as a way to give predefined values which IDEs' auto-completion features could understand.

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

Constants do the trick, but there's the namespace collision problem and (or actually because) they're global. Arrays don't have the namespace problem, but they're too vague, they can be overwritten at runtime and IDEs rarely know how to autofill their keys without additional static analysis annotations or attributes.

是否有您常用的解决方案/变通办法?有没有人记得 PHP 的人是否对枚举有任何想法或决定?

Are there any solutions/workarounds you commonly use? Does anyone recall whether the PHP guys have had any thoughts or decisions around enumerations?

推荐答案

根据用例,我通常会使用类似以下的简单:

Depending upon use case, I would normally use something simple like the following:

abstract class DaysOfWeek
{
    const Sunday = 0;
    const Monday = 1;
    // etc.
}

$today = DaysOfWeek::Sunday;

但是,其他用例可能需要对常量和值进行更多验证.基于下面关于反射的评论,以及一些其他说明,这里有一个扩展的例子,可以更好地服务于更广泛的范围案例数:

However, other use cases may require more validation of constants and values. Based on the comments below about reflection, and a few other notes, here's an expanded example which may better serve a much wider range of cases:

abstract class BasicEnum {
    private static $constCacheArray = NULL;

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

    public static function isValidName($name, $strict = false) {
        $constants = self::getConstants();

        if ($strict) {
            return array_key_exists($name, $constants);
        }

        $keys = array_map('strtolower', array_keys($constants));
        return in_array(strtolower($name), $keys);
    }

    public static function isValidValue($value, $strict = true) {
        $values = array_values(self::getConstants());
        return in_array($value, $values, $strict);
    }
}

通过创建一个扩展 BasicEnum 的简单枚举类,您现在可以使用方法来进行简单的输入验证:

By creating a simple enum class that extends BasicEnum, you now have the ability to use methods thusly for simple input validation:

abstract class DaysOfWeek extends BasicEnum {
    const Sunday = 0;
    const Monday = 1;
    const Tuesday = 2;
    const Wednesday = 3;
    const Thursday = 4;
    const Friday = 5;
    const Saturday = 6;
}

DaysOfWeek::isValidName('Humpday');                  // false
DaysOfWeek::isValidName('Monday');                   // true
DaysOfWeek::isValidName('monday');                   // true
DaysOfWeek::isValidName('monday', $strict = true);   // false
DaysOfWeek::isValidName(0);                          // false

DaysOfWeek::isValidValue(0);                         // true
DaysOfWeek::isValidValue(5);                         // true
DaysOfWeek::isValidValue(7);                         // false
DaysOfWeek::isValidValue('Friday');                  // false

作为旁注,每当我至少使用反射一次在数据不会改变的静态/常量类(例如在枚举中)时,我都会缓存这些结果反射调用,因为每次使用新的反射对象最终都会对性能产生明显影响(存储在多个枚举的关联数组中).

As a side note, any time I use reflection at least once on a static/const class where the data won't change (such as in an enum), I cache the results of those reflection calls, since using fresh reflection objects each time will eventually have a noticeable performance impact (Stored in an assocciative array for multiple enums).

既然大多数人已经最终升级到至少 5.3,并且 SplEnum 可用,那么这当然也是一个可行的选择——只要你不这样做'不要介意在整个代码库中具有实际枚举实例化的传统上不直观的概念.在上面的例子中,BasicEnumDaysOfWeek 根本不能被实例化,也不应该被实例化.

Now that most people have finally upgraded to at least 5.3, and SplEnum is available, that is certainly a viable option as well--as long as you don't mind the traditionally unintuitive notion of having actual enum instantiations throughout your codebase. In the above example, BasicEnum and DaysOfWeek cannot be instantiated at all, nor should they be.

这篇关于PHP 上的枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆