PHP Enums
Enums is the biggest of the new features that came with PHP 8.1. This post will outline everything to do with enums in PHP, and will be updated as they change in future releases of the PHP language.
Table of Contents
- Creation and Usage
- Methods
- Interfaces
- Typed Enums
- Retrieve Value
- Built-in Methods
- Cases method - Get Array of Cases
- Comparing Enums
- Array Keys
Creation And Usage
Declare an enum like so:
enum Status
{
case DRAFT;
case PUBLISHED;
case ARCHIVED;
}
Define a class that can take an enum like so:
class BlogPost
{
private Status $m_status;
public function __construct(Status $status)
{
$this->m_status = $status;
}
}
Create and pass the status enum like so:
$post = new BlogPost(Status::DRAFT);
Enum Methods
One can define and use methods on an enum, although I'm not sure this is generally adviseable.
The following method will return a colour based on the status. E.g.
enum Status
{
case DRAFT;
case PUBLISHED;
case ARCHIVED;
/**
* Return a the colour to represent the status.
* @return string - the name of the colour.
*/
public function colour(): string
{
$colour = match($this) {
self::DRAFT => "grey",
self::PUBLISHED => "green",
self::ARCHIVED => "red"
};
return $colour;
}
}
... and an example of this would be:
$status = Status::DRAFT;
$colour = $status->colour();
Magic Methods Not Allowed
You may be tempted to add a __toString
magic method for casting to a string. Unfortunately this is not allowed. One will need to either:
- Specify a different name and manually call that method.
- Use the built-in
name
property to output the name. E.g.
print "Log level string: " . $loglevel->name . PHP_EOL;
Enum Interfaces
Since enums can have methods, it makes sense that they can also implement interfaces which would specify required public methods that must be implemented.
Backed/Typed Enums
One can declare that the values for enums are either strings or integers like so:
enum Status: string
{
case DRAFT = "draft";
case PUBLISHED = "published";
case ARCHIVED = "archived";
}
...or:
enum Status: int
{
case DRAFT = 1;
case PUBLISHED = 2;
case ARCHIVED = 3;
}
Retrieve Enum Value
One can get the value of a backed enum using the value
public property like so:
print Status::PUBLISHED->value; // 2
Built In Methods
From
Likewise, one can create the enum from the numerical value (good for when converting from database row).
$row = $result->fetch_assoc();
$status = Status::from($row['status']); // assuming $row['status'] is the number 2
TryFrom Value
The from()
method will throw an exception if the value passed is not recognized by the enum. If you would prefer a null
to be returned in such a scenario, then use tryFrom()
instead.
$status = Status::tryFrom(100); // $status is null because the status enum does not have a case for 100.
Serialize, Unserialize, and Json Encode
Enums have built in serialize()
and unserialize()
methods. Likewize, if you used backed enums, json_encode will automatically return the typed value.
Cases() method - Get Array Of Cases
If you want to get an array of the cases for an enum, call the cases static method.
<?php
enum Status: string
{
case PENDING = 'pending';
case ACCEPTED = 'accepted';
case DENIED = 'denied';
}
$enumsArr = Status::cases();
$names = array_column($enumsArr, 'name');
$values = array_column($enumsArr, 'value');
print "cases output: " . print_r($enumsArr, true) . PHP_EOL;
print "names: " . PHP_EOL . print_r($names, true) . PHP_EOL;
print "values: " . PHP_EOL . print_r($values, true) . PHP_EOL;
Outputs:
cases output: Array
(
[0] => Status Enum:string
(
[name] => PENDING
[value] => pending
)
[1] => Status Enum:string
(
[name] => ACCEPTED
[value] => accepted
)
[2] => Status Enum:string
(
[name] => DENIED
[value] => denied
)
)
names:
Array
(
[0] => PENDING
[1] => ACCEPTED
[2] => DENIED
)
values:
Array
(
[0] => pending
[1] => accepted
[2] => denied
)
Comparison
One can compare enums against each other like so:
if ($post1->getStatus() === $post2->getStatus())
{
// do something.
}
Array Keys
Due to the fact that enums are objects, you cannot use them as array keys, which may likely change in the future. However, you could do the following:
$list = [
$myEnum->value => "foo",
$mySecondEnum->value => "bar",
];
References
First published: 29th November 2021