PHP 8.1 enums: a simple example

Published on Feb 02, 2022

PHP 8.1 introduces enums or enumerations which can be described as a data type that contains a predefined set of values you can use. When you are developing an app often come accross situations where you have a preset of options you want to choose from, for example:

  • a blog post can be published, draft or unpublished
  • a player can be of type medic, soldier or engineer
  • a ticket can be either VIP, standing or seated
  • and so on ...

You may have used arrays or classes with constants in them to create this kind of functionality like so:

<?php 
    class PostType {
        const Draft = 0;
        const Published = 1;
        const Unpublished = 2;
    }

    class Post {
        public function __construct(public string $title, public int $type){}
    }

    // this works
    $post = new Post('Hello', PostType::Published);
    echo $post->type; // 1
?>

This works, but the problem is that we need to write extra code to check if the PostType is 0, 1, or 2 and we probably don't want to do that. Without those checks, the following works as well:

// oops, this works as well
$post = new Post('Hello', 666);
echo $post->type; // 666

Enums can solve that problem without the need for extra unnecessary code. Here's how we can re-write the code above with a simple enum structure to do the same thing: make sure we can only set the blog post type to one of three possible values.

Using enums in PHP

First, we need to create the enum structure by using the enum keyword and defining the possible cases that are valid for this structure.

enum PostType {
  case Draft;
  case Published;
  case Unpublished;
}

Next, we can update our function that requires a PostType but this time we're not just expecting an integer. Instead, we are telling our function to expect a variable of type PostType.

class Post {
  public function __construct(public string $title, public PostType $type){}
}

Now, we can try to use this class in order to instantiate a new Post like so:

try {
  // this works
  $post = new Post('Hello', PostType::Published);

  // this will trigger an Exception
  $post = new Post('Hello', 666);
} catch (Throwable $e) {
  echo $e->getMessage();
}

When trying to set 666 as the PostType PHP will throw an Exception because 666 is not of type PostType.

Post::__construct(): Argument #2 ($type) must be of type PostType, int given

Pure versus Backed Enums

You may have noticed that it's not so easy to use PostType::Published in a database query, because in your database you most likely want to store this type as an integer (draft = 0, published = 1, ...).

Enums come in different tastes to do just that. In the example above we simply defined a couple of possible cases that we could use without attaching a value to those choices. These enums are called pure enums.

If we want to be able to attach values to an enum, these are called backed enums and they work pretty much in the same way.

Currently, we can't just grab the post type to use in a query because we'll see the following error when we try to print the type.

$post = new Post('Hello', PostType::Published);

// The line below will trigger an error:
// Object of class PostType could not be converted to string
echo "Post Type is: " . $post->type; 

Let's first attach values to our enum cases like so (we are attaching value and are setting the return type for the enum as well)

enum PostType: int {
  case Draft = 0;
  case Published = 1;
  case Unpublished = 2;
}

Now we can ask for the corresponding value for any of the cases in the enum by calling the value:

$post = new Post('Hello', PostType::Published);
echo "Post Type is: " . $post->type->value; // Post Type is: 1

This way, you can use enums to better control what choices can be set in specific situations while still being able to get the exact values matching those choices for later use in queries.

Putting it all together, the example may look like this:

<?php 
    enum PostType: int {
        case Draft = 0;
        case Published = 1;
        case Unpublished = 2;
    }

    class Post {
        public function __construct(public string $title, public PostType $type){}
    }

    try {
        $post = new Post('Hello', PostType::Published);
        echo "Post Type is: " . $post->type->value; // Post Type is: 1

    } catch (Throwable $e) {
        echo $e->getMessage();
    }

?>

Conclusion

Enums are a great addition to PHP for making it easier to come up with a data type that allows you to pick from a pre-defined set of choices with matching values.

In this article I barely scratched the surface of what you can do with enums but I found this article to be a great resource that shows you all the details of what you can do with enums.

No comments? But that’s like a Gin & Tonic without the ice?

I’ve removed the comments but you can shoot me a message on LinkedIn to keep the conversation going.