PHP and Enumerations

后端 未结 30 1939
有刺的猬
有刺的猬 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 13:56

    Stepping on the answer of @Brian Cline I thought I might give my 5 cents

    
     * class Season extends Enum{
     *    const Spring  = 0;
     *    const Summer = 1;
     *    const Autumn = 2;
     *    const Winter = 3;
     * }
     * 
     * $currentSeason = new Season(Season::Spring);
     * $nextYearSeason = new Season(Season::Spring);
     * $winter = new Season(Season::Winter);
     * $whatever = new Season(-1);               // Throws InvalidArgumentException
     * echo $currentSeason.is(Season::Spring);   // True
     * echo $currentSeason.getName();            // 'Spring'
     * echo $currentSeason.is($nextYearSeason);  // True
     * echo $currentSeason.is(Season::Winter);   // False
     * echo $currentSeason.is(Season::Spring);   // True
     * echo $currentSeason.is($winter);          // False
     * 
     * 
     * Class Enum
     * 
     * PHP Version 5.5
     */
    abstract class Enum
    {
        /**
         * Will contain all the constants of every enum that gets created to 
         * avoid expensive ReflectionClass usage
         * @var array
         */
        private static $_constCacheArray = [];
        /**
         * The value that separates this instance from the rest of the same class
         * @var mixed
         */
        private $_value;
        /**
         * The label of the Enum instance. Will take the string name of the 
         * constant provided, used for logging and human readable messages
         * @var string
         */
        private $_name;
        /**
         * Creates an enum instance, while makes sure that the value given to the 
         * enum is a valid one
         * 
         * @param mixed $value The value of the current
         * 
         * @throws \InvalidArgumentException
         */
        public final function __construct($value)
        {
            $constants = self::_getConstants();
            if (count($constants) !== count(array_unique($constants))) {
                throw new \InvalidArgumentException('Enums cannot contain duplicate constant values');
            }
            if ($name = array_search($value, $constants)) {
                $this->_value = $value;
                $this->_name = $name;
            } else {
                throw new \InvalidArgumentException('Invalid enum value provided');
            }
        }
        /**
         * Returns the constant name of the current enum instance
         * 
         * @return string
         */
        public function getName()
        {
            return $this->_name;
        }
        /**
         * Returns the value of the current enum instance
         * 
         * @return mixed
         */
        public function getValue()
        {
            return $this->_value;
        }
        /**
         * Checks whether this enum instance matches with the provided one.
         * This function should be used to compare Enums at all times instead
         * of an identity comparison 
         * 
         * // Assuming EnumObject and EnumObject2 both extend the Enum class
         * // and constants with such values are defined
         * $var  = new EnumObject('test'); 
         * $var2 = new EnumObject('test');
         * $var3 = new EnumObject2('test');
         * $var4 = new EnumObject2('test2');
         * echo $var->is($var2);  // true
         * echo $var->is('test'); // true
         * echo $var->is($var3);  // false
         * echo $var3->is($var4); // false
         * 
         * 
         * @param mixed|Enum $enum The value we are comparing this enum object against
         *                         If the value is instance of the Enum class makes
         *                         sure they are instances of the same class as well, 
         *                         otherwise just ensures they have the same value
         * 
         * @return bool
         */
        public final function is($enum)
        {
            // If we are comparing enums, just make
            // sure they have the same toString value
            if (is_subclass_of($enum, __CLASS__)) {
                return get_class($this) === get_class($enum) 
                        && $this->getValue() === $enum->getValue();
            } else {
                // Otherwise assume $enum is the value we are comparing against
                // and do an exact comparison
                return $this->getValue() === $enum;   
            }
        }
    
        /**
         * Returns the constants that are set for the current Enum instance
         * 
         * @return array
         */
        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];
        }
    }
    

提交回复
热议问题