Enum Support in PHP






4.80/5 (4 votes)
Here, I’ll give you my version of enum support. If you like this approach, or if you prefer any other one, it is basically a matter of taste.
As any PHP developer knows, there is no native enum
support in PHP due to the fact that PHP is a dynamic language where a variable can be anything and everything. Many have tried to implement their own version of enum
support, some solutions working better than others. Here, I’ll give you my version of enum
support. If you like this approach, or if you prefer any other one, it is basically a matter of taste.
An Abstract Enum Template Class
The basic idea behind the enum
support is an abstract enum
class with the simple functionality we want the enum
to have. It includes type checking where you can check if a variable is of a certain enum
type and also the possibility to verify that only allowed enum
values are being used.
This is the code for the abstract
class:
abstract class Enum {
protected $value;
/**
* Return string representation of this enum
*
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* Tries to set the value of this enum
*
* @param string $value
* @throws Exception If value is not part of this enum
*/
public function setValue($value)
{
if ($this->isValidEnumValue($value))
$this->value = $value;
else
throw new Exception("Invalid type specified!");
}
/**
* Validates if the type given is part of this enum class
*
* @param string $checkValue
* @return bool
*/
public function isValidEnumValue($checkValue)
{
$reflector = new ReflectionClass(get_class($this));
foreach ($reflector->getConstants() as $validValue)
{
if ($validValue == $checkValue) return true;
}
return false;
}
/**
* @param string $value Value for this display type
*/
function __construct($value)
{
$this->setValue($value);
}
/**
* With a magic getter you can get the value from this enum using
* any variable name as in:
*
* <code>
* $myEnum = new MyEnum(MyEnum::start);
* echo $myEnum->v;
* </code>
*
* @param string $property
* @return string
*/
function __get($property)
{
return $this->value;
}
/**
* With a magic setter you can set the enum value using any variable
* name as in:
*
* <code>
* $myEnum = new MyEnum(MyEnum::Start);
* $myEnum->v = MyEnum::End;
* </code>
*
* @param string $property
* @param string $value
* @throws Exception Throws exception if an invalid type is used
*/
function __set($property, $value)
{
$this->setValue($value);
}
/**
* If the enum is requested as a string then this function will be automatically
* called and the value of this enum will be returned as a string.
*
* @return string
*/
function __toString()
{
return (string)$this->value;
}
}
How to Create Your Own Enum
To create your own enum
using this abstract
class, simply do in the following way:
class MyEnum extends Enum {
const TypeA = "1";
const TypeB = "2";
const TypeC = "3";
}
The only thing your class should contain is constants with the values of your enum
. Why the integers are written as string
s is explained further down. It’s not mandatory, but it brings some extra possibilities.
To use the new enum
in code, simply write in the following way:
// Create a new enum with a given value
$myType = new MyEnum(MyEnum::TypeB);
// Change value of enum
$myType->setValue(MyEnum::TypeC);
// Check value of enum
if ($myType == MyEnum::TypeC) {
// do something
}
// Verify that variable is of enum type
if ($myType instanceof MyEnum) {
// do something
}
// Force type checking in function definitions
function myFunction(MyEnum $myType)
{
// do something
}
Notes on the Abstract Enum Class
The code for the abstract enum
class is quite straight forward, but there are a few things I would like to highlight:
- The magic
__get
and__set
are not at all needed. They just add an easier way to get and set the value of theenum
. Instead of, as in the code above, typing$myType->setValue(MyEnum::TypeC);
you can shorten it down to just$myType->v = MyEnum::TypeC;
. Your IDE might complain that you’re accessing a dynamically assigned variable, but in ourabstract enum
class, all dynamic variables are redirected to theprotected $value
variable, and you won’t get any errors when you run it. - When you create an instance of the
enum
, you simply create an object. To access the actual value of thatenum
object, you have to use thegetValue()
function. But if you usestring enum
values (as illustrated further up) you can use the magic__string()
function to access theenum
’s value right off from the object, as illustrated here:$e = new MyEnum(MyEnum::Start); if ($e == MyEnum::TypeA) { // Do something }
This only works if you define yourenum
values asstring
s as illustrated in the example earlier, and if you try to access theenum
as astring
. The reason for this is that there is no “magic” way of converting objects toint
s (or other datatypes) but you can convert them tostring
s. IfTypeA
was an integer PHP would try to convert$e
to integer to match, and that would fail. - In the
isValidEnumValue()
method (in theabstract
class) you can’t use the__CLASS__
constant because it refers to theabstract
class and not to the class extending it. Instead, we have to useget_class($this)
to get the class name of the class extending theenum
.
Limitations Using This Type of Enum
When you use enum
s in a language having it built in, you also have an “enum
understanding” in each and every enum
value. That’s not the case here where each value is a string
(or int
). You therefore have to take a little longer way to set an enum
, as illustrated here:
// First way of setting to TypeA
$myType = new MyEnum(MyEnum::TypeA);
// Second way of setting to TypeA
$myType = new MyEnum(MyEnum::TypeC);
$myType->setValue(MyEnum::TypeA);
// This way doesn't work at all though
$myType = MyEnum::TypeA;
If you can live with that, you might have found a decent enum
implementation in PHP.
More Reading
If you want to read some more about the different PHP techniques used in this solution, you can continue here:
- PHP manual on get_class
- PHP manual on magic methods
And here are some links to other people’s suggestions on enum
support in PHP:
- Enums in PHP – A Native Implementation by Jonathan Hohle
- Java-inspired enumerated types in PHP by Guy Paddock