PHP and Enumerations

后端 未结 30 2128
有刺的猬
有刺的猬 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:58

    My Enum class definition below is Strongly typed, and very natural to use and define.

    Definition:

    class Fruit extends Enum {
        static public $APPLE = 1;
        static public $ORANGE = 2;
    }
    Fruit::initialize(); //Can also be called in autoloader
    

    Switch over Enum

    $myFruit = Fruit::$APPLE;
    
    switch ($myFruit) {
        case Fruit::$APPLE  : echo "I like apples\n";  break;
        case Fruit::$ORANGE : echo "I hate oranges\n"; break;
    }
    
    >> I like apples
    

    Pass Enum as parameter (Strongly typed)

    /** Function only accepts Fruit enums as input**/
    function echoFruit(Fruit $fruit) {
        echo $fruit->getName().": ".$fruit->getValue()."\n";
    }
    
    /** Call function with each Enum value that Fruit has */
    foreach (Fruit::getList() as $fruit) {
        echoFruit($fruit);
    }
    
    //Call function with Apple enum
    echoFruit(Fruit::$APPLE)
    
    //Will produce an error. This solution is strongly typed
    echoFruit(2);
    
    >> APPLE: 1
    >> ORANGE: 2
    >> APPLE: 1
    >> Argument 1 passed to echoFruit() must be an instance of Fruit, integer given
    

    Echo Enum as string

    echo "I have an $myFruit\n";
    
    >> I have an APPLE
    

    Get Enum by integer

    $myFruit = Fruit::getByValue(2);
    
    echo "Now I have an $myFruit\n";
    
    >> Now I have an ORANGE
    

    Get Enum by Name

    $myFruit = Fruit::getByName("APPLE");
    
    echo "But I definitely prefer an $myFruit\n\n";
    
    >> But I definitely prefer an APPLE
    

    The Enum Class:

    /**
     * @author Torge Kummerow
     */
    class Enum {
    
        /**
         * Holds the values for each type of Enum
         */
        static private $list = array();
    
        /**
         * Initializes the enum values by replacing the number with an instance of itself
         * using reflection
         */
        static public function initialize() {
            $className = get_called_class();
            $class = new ReflectionClass($className);
            $staticProperties = $class->getStaticProperties();
    
            self::$list[$className] = array();
    
            foreach ($staticProperties as $propertyName => &$value) {
                if ($propertyName == 'list')
                    continue;
    
                $enum = new $className($propertyName, $value);
                $class->setStaticPropertyValue($propertyName, $enum);
                self::$list[$className][$propertyName] = $enum;
            } unset($value);
        }
    
    
        /**
         * Gets the enum for the given value
         *
         * @param integer $value
         * @throws Exception
         *
         * @return Enum
         */
        static public function getByValue($value) {
            $className = get_called_class();
            foreach (self::$list[$className] as $propertyName=>&$enum) {
                /* @var $enum Enum */
                if ($enum->value == $value)
                    return $enum;
            } unset($enum);
    
            throw new Exception("No such enum with value=$value of type ".get_called_class());
        }
    
        /**
         * Gets the enum for the given name
         *
         * @param string $name
         * @throws Exception
         *
         * @return Enum
         */
        static public function getByName($name) {
            $className = get_called_class();
            if (array_key_exists($name, static::$list[$className]))
                return self::$list[$className][$name];
    
            throw new Exception("No such enum ".get_called_class()."::\$$name");
        }
    
    
        /**
         * Returns the list of all enum variants
         * @return Array of Enum
         */
        static public function getList() {
            $className = get_called_class();
            return self::$list[$className];
        }
    
    
        private $name;
        private $value;
    
        public function __construct($name, $value) {
            $this->name = $name;
            $this->value = $value;
        }
    
        public function __toString() {
            return $this->name;
        }
    
        public function getValue() {
            return $this->value;
        }
    
        public function getName() {
            return $this->name;
        }
    
    }
    

    Addition

    You can ofcourse also add comments for IDEs

    class Fruit extends Enum {
    
        /**
         * This comment is for autocomplete support in common IDEs
         * @var Fruit A yummy apple
         */
        static public $APPLE = 1;
    
        /**
         * This comment is for autocomplete support in common IDEs
         * @var Fruit A sour orange
         */
        static public $ORANGE = 2;
    }
    
    //This can also go to the autoloader if available.
    Fruit::initialize();
    

提交回复
热议问题