Programster's Blog

Tutorials focusing on Linux, programming, and open-source

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

  1. Creation and Usage
  2. Methods
    1. Magic Methods Not allowed
  3. Interfaces
  4. Typed Enums
  5. Retrieve Value
  6. Built-in Methods
    1. Create from Value
    2. from()
    3. tryFrom()
    4. Serialize
  7. Cases method - Get Array of Cases
  8. Comparing Enums
  9. 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;
    }
}

Documentation for match().

... 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;
}

If specifying a type, then all cases need to have a number/string assignment of the same type.

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

Last updated: 29th January 2024
First published: 29th November 2021