PHP and Enumerations

后端 未结 30 2205
有刺的猬
有刺的猬 2020-11-22 13:39

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 whi

30条回答
  •  说谎
    说谎 (楼主)
    2020-11-22 14:17

    I know this is an old thread, however none of the workarounds I've seen really looked like enums, since almost all workarounds requires you to manually assign values to the enum items, or it requires you to pass an array of enum keys to a function. So I created my own solution for this.

    To create an enum class using my solution one can simply extend this Enum class below, create a bunch of static variables (no need to initialize them), and make a call to yourEnumClass::init() just below the definition of your enum class.

    edit: This only works in php >= 5.3, but it can probably be modified to work in older versions as well

    /**
     * A base class for enums. 
     * 
     * This class can be used as a base class for enums. 
     * It can be used to create regular enums (incremental indices), but it can also be used to create binary flag values.
     * To create an enum class you can simply extend this class, and make a call to ::init() before you use the enum.
     * Preferably this call is made directly after the class declaration. 
     * Example usages:
     * DaysOfTheWeek.class.php
     * abstract class DaysOfTheWeek extends Enum{
     *      static $MONDAY = 1;
     *      static $TUESDAY;
     *      static $WEDNESDAY;
     *      static $THURSDAY;
     *      static $FRIDAY;
     *      static $SATURDAY;
     *      static $SUNDAY;
     * }
     * DaysOfTheWeek::init();
     * 
     * example.php
     * require_once("DaysOfTheWeek.class.php");
     * $today = date('N');
     * if ($today == DaysOfTheWeek::$SUNDAY || $today == DaysOfTheWeek::$SATURDAY)
     *      echo "It's weekend!";
     * 
     * Flags.class.php
     * abstract class Flags extends Enum{
     *      static $FLAG_1;
     *      static $FLAG_2;
     *      static $FLAG_3;
     * }
     * Flags::init(Enum::$BINARY_FLAG);
     * 
     * example2.php
     * require_once("Flags.class.php");
     * $flags = Flags::$FLAG_1 | Flags::$FLAG_2;
     * if ($flags & Flags::$FLAG_1)
     *      echo "Flag_1 is set";
     * 
     * @author Tiddo Langerak
     */
    abstract class Enum{
    
        static $BINARY_FLAG = 1;
        /**
         * This function must be called to initialize the enumeration!
         * 
         * @param bool $flags If the USE_BINARY flag is provided, the enum values will be binary flag values. Default: no flags set.
         */ 
        public static function init($flags = 0){
            //First, we want to get a list of all static properties of the enum class. We'll use the ReflectionClass for this.
            $enum = get_called_class();
            $ref = new ReflectionClass($enum);
            $items = $ref->getStaticProperties();
            //Now we can start assigning values to the items. 
            if ($flags & self::$BINARY_FLAG){
                //If we want binary flag values, our first value should be 1.
                $value = 1;
                //Now we can set the values for all items.
                foreach ($items as $key=>$item){
                    if (!isset($item)){                 
                        //If no value is set manually, we should set it.
                        $enum::$$key = $value;
                        //And we need to calculate the new value
                        $value *= 2;
                    } else {
                        //If there was already a value set, we will continue starting from that value, but only if that was a valid binary flag value.
                        //Otherwise, we will just skip this item.
                        if ($key != 0 && ($key & ($key - 1) == 0))
                            $value = 2 * $item;
                    }
                }
            } else {
                //If we want to use regular indices, we'll start with index 0.
                $value = 0;
                //Now we can set the values for all items.
                foreach ($items as $key=>$item){
                    if (!isset($item)){
                        //If no value is set manually, we should set it, and increment the value for the next item.
                        $enum::$$key = $value;
                        $value++;
                    } else {
                        //If a value was already set, we'll continue from that value.
                        $value = $item+1;
                    }
                }
            }
        }
    }
    

提交回复
热议问题