Introduction to PHP Enums

Introduction to PHP Enums
Photo by Dan Cristian Pădureț / Unsplash

PHP 8.1 finally brings enums which can be know from other programming languages like C#. It is in my opinion one of best things which came with new php version.

Enums

Prior enums you maybe used static classes like me or you have installed enum composer package. Enums can be defined with word enum instead of class following with enum name. Values are defined witch word case following name of value. Enum defined as bellow returns for each value it's number in order from 1.

enum DocumentType
{
    case order; //1
    case invoice; //2
    case orderItem; //3
}

then using is obvious

DocumentType::order //enum(DocumentType::order)

reutrn type of each case is enum(DocumentType::<case-name>). If you vant to get value of case you have to add value keyword to you call

DocumentType::order->value //1

You can also get enum from value as bellow

DocumentType::from(2) //enum(DocumentType::order)

if you try to pass to from() something that not exist in your enum it will throw \ValueError whic can be easily handled with try catch.

Backed enums

Tere are something called "backed enums" which are basically same as standard enums but you can define for each enum value (property) value and type which you like, for example

enum DocumentType: string
{
    case order = 'application/disclosure.document.order';
    case invoice = 'application/disclosure.document.invoice';
    case orderItem = 'application/disclosure.document.order-item';
}

Using is same as with normal enums but as return of value you get string that you defined instad of order number. For example:

DocumentType::order->value //application/disclosure.document.order

Using with other classes

As i said prior enums I used static classes with some defined properties like one bellow

class ImportDocumentType
{
    public static string $order = "application/disclosure.document.order";

    public static string $orderItem = "application/disclosure.document.order-item";

    public static string $invoice = "application/disclosure.document.invoice";

    public static function get(string $property): string
    {
        if (property_exists(self::class, $property)) {
            return self::$$property;
        } else {
            throw new \InvalidArgumentException("Property $property does not exist in class " . self::class);
        }
    }
}

It is much more text as you can see and it not ideal (but as example its enough). Than in class you can use it as bellow. (i use interfaces because it's simpler)

interface Document
{
    protected string $type;

    public function __construct(string $type);

    public function getType(): string;
}

Calling ImportDocumentType::$order has return type of string and returns just value of that variable. So as you can see __construct() of my class accepts any string which is not ideal, because you can put there anything. getType() function simmilary returns just string that you put there - which don't have to be just ImportDocumentType.

As someone who really love to use typed properties (not just in PHP but in other languages too), because code looks much more clean and you still know what you get in return when calling your functions, I can agree with people who tells that the PHP code is a mess. It was and I almost ditch PHP just for that, but with new version it is a lot better.

Back to my class, with enums it can looks like one bellow

interface Document
{
    protected DocumentType $type;

    public function __construct(DocumentType $type);

    public function getType(): DocumentType;
}

It is much better isnt it? And I know that $type in __construct() can only be DocumentType and nothing else. Simmilar it is when you calling getType() and you know you can only get DocumentType.

In the end

As you can see using enums is easy (you don't need to define our functions), using enums ensure that variable can be only enum and not any other string as from my example above.

Do you like new additions in PHP? I love them and I am excited what will brings us new versions of it.