Enumerations in PHP

In the C programming language, enumerations are handy little data types, which add more linguistic context to the code. They make code more readable, and enforce variables to have certain values. The latter is certainly true, if you have ever assigned string-valued codes to your variables and made a typo somewhere. For example assigning 'white' to the variable $color, and then make a typo somewhere in the code by using 'whiet' or something like that. The program would still compile or run, and not complain at all, while there is something fundamentally wrong with the code.

So a C example of an enumeration would be like:

typedef enum {
  white,
  black,
  red,
  blue
} color;
 
color c = red; // Totally fine.

Under the hood, C assigns the first entry a value of 0, and every subsequent entry is an increase by 1. So typically it is the same as:

int c = 2;

But much more readable because you know it is about a color, and that it is red.

PHP does not have a built-in mechanism for enumerations like C. This is probably because PHP is a loosely-typed language and does not complain if you assign something non-related to your variables. However, if you are like me, and want to maintain a degree of consistency and readability, you could create an abstract class defining the constants.

Often, you would like to show these options in a pull-down control as well, so you would like to be able to extract all the available options, and their textual representations. Here is a class that could do this for you:

abstract class Enum
{
    public static function getValues()
    {
        $reflection = new ReflectionClass(get_called_class());
        $constants = $reflection->getConstants();
 
        $ret = array();
        foreach($constants as $val) $ret[$val] = static::str($val);
        return $ret;
    }
 
    public static function str($item)
    {
        return '(unknown)';
    }
}

This class exposes a getValues() function that collects the defined class constants, and gives you back a key-value list of their entries and their textual representations. Of course you’d need to overload the str() in your derived classes to give the entries their textual representations.

An example usage would be:

abstract class Enum_Color extends Enum
{
    const WHITE = "white";
    const BLACK = "black";
    const RED = "red";
    const BLUE = "blue";
 
    public static function str($item)
    {
        $ret = parent::str($item);
 
        if ($item == self::WHITE) $ret = 'Blanco';
        if ($item == self::BLACK) $ret = 'Negro';
        if ($item == self::RED) $ret = 'Rojo';
        if ($item == self::BLUE) $ret = 'Azul';
 
        return $ret;
    }
}

Then you can use this enumeration as follows:

$color = Enum_Color::BLUE;
echo $color . " => " . Enum_Color::str($color) . PHP_EOL;
// Outputs "blue => Azul"
 
var_dump(Enum_Color::getValues());
// Outputs an array like array(
//   'white' => 'Blanco',
//   'black' => 'Negro',
//   'red' => 'Rojo',
//   'blue' => 'Azul'
// )

An implementation of this class has been added to the ZFE library, with an example in the comments that uses the ZFE_MultiLanguage plugin instead of the hard-coded values I used in this example.

Last but not least, I said there is no built-in type for enumerations in PHP, but there is an SplEnum class in the spl_types PECL extension. I don’t like it much as you create object instances with new and that just… doesn’t make sense to me for enumerations… What is your opinion?

What are your thoughts?