PHP 8.1 - Enums

Enfin ! C’était devenu une sorte de serpent de mer : les enums en PHP. On a très longtemps du “bricoler” ou mieux utiliser des libraires comme https://github.com/myclabs/php-enum par exemple. Depuis PHP 8.1, les enums sont natifs au langage. On peut résumer grossièrement un enum en un ensemble de constantes typées. On peut donc “typehinter” les paramètres ou les retours de nos méthodes avec. Cet ensemble permet de définir une liste de valeurs prévues et empêche donc potentiellement de se retrouver avec des valeurs inattendues sur une propriété. Par exemple, si on a une porte avec un statut qui peut être ouvert ou fermé, utiliser un enum empêchera d’avoir une valeur qui n’aurait pas de sens sur une porte.

enum DoorStatus
{
    case OPEN;
    case CLOSE;
}

class Door
{
    public function changeState(DoorStatus $doorStatus) {}
}

$door = new Door();
$door->changeState(DoorStatus::OPEN);

Un enum est un type de classe, donc il est possible d’avoir des méthodes dessus. Il est aussi possible d’implémenter des interfaces.

interface Status {}

enum DoorStatus implements Status
{
    case OPEN;
    case CLOSE;

    public function foo(): string
    {
        ...
    }
}

On peut assigner une valeur (et donc avoir un type int ou string uniquement) à un enum, ça peut permettre de le stocker en bdd par exemple. Si un “case” a une valeur, tous les “cases” doivent en avoir une aussi et du même type.

enum DoorStatus: string // string est le type de l'enum
{
    case OPEN = 'open';
    case CLOSE = 'close';

    public function foo(): string {}
}

echo DoorStatus::OPEN->value; // print open

Un enum possède une propriété readonly si on veut écrire sa valeur mais il est spécifié dans la RFC qu’on ne devrait globalement l’utiliser que pour débugger uniquement. Cette propriété est name;

enum Foo 
{
    case Bar;
}

echo Foo::Bar; // Error: Object of class Foo could not be converted to string
echo Foo::Bar->name; // print Bar 

Pour avoir un enum depuis une valeur il existe une méthode :

$doorStatus = DoorStatus::from('open');
$doorStatus = DoorStatus::from('red'); // ValueError: "red" is not a valid backing value for enum "DoorStatus"
$doorStatus = DoorStatus::tryFrom('red'); // null

Une méthode cases()permet d’avoir la liste des “cases” :

print_r(DoorStatus::cases());
//Array
//(
//    [0] => DoorStatus Enum:string
//        (
//            [name] => OPEN
//            [value] => open
//        )
//    [1] => DoorStatus Enum:string
//        (
//            [name] => CLOSE
//            [value] => close
//        )
//)

Conclusion

Cette présentation n’est pas exhaustive mais reprend les principales informations. Les enums sont vraiment un ajout très important à PHP et c’est top de pouvoir utiliser ça dans notre code !