PHP和枚举 [英] PHP and Enumerations

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

问题描述

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

I know that PHP doesn't 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 (never?) know how to autofill their keys.

您是否通常使用任何解决方案/解决方法?有谁记得PHP家伙是否对枚举有任何想法或决定?

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

推荐答案

根据使用情况,我通常会使用简单这样的东西:

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天全站免登陆