Comment utiliser les énumérations en PHP 8.1

0
307

PHP 8.1 ajoutera enfin la prise en charge des langues pour les énumérations. Les énumérations, abréviation d'énumérations, sont des types qui ne peuvent être instanciés qu'avec des valeurs spécifiques. Ils sont couramment trouvés dans d'autres langages orientés objet, mais ont déjà nécessité des solutions de contournement utilisateur pour implémenter en PHP.

Syntaxe de base

Ici&#8217 ;s à quoi ressemble une simple énumération :

enum PostStatus { cas Publié; cas InReview; cas Brouillon; }

Le mot-clé case, qui faisait auparavant partie des instructions switch, est utilisé pour délimiter les valeurs spécifiques acceptées par l'énumération. Les valeurs sont référencées de la même manière que les constantes de classe :

$published = PostStatus::Published;

Les énumérations se comportent de la même manière que les classes et les interfaces. Ils’sont entièrement compatibles avec le système de types, vous pouvez donc indiquer qu'une fonction n'accepte qu'une valeur définie dans une énumération :

class BlogPost {   fonction publique __construct( chaîne publique $Headline, chaîne publique $Content, public PostStatus $Status=PostStatus::Draft) {}   }

Voici un exemple d'utilisation de la classe BlogPost :

//OK $post = nouveau BlogPost( "Exemple de publication", "Un exemple", PostStatus::Brouillon );   //TypeError : l'argument #3 ($Status) doit être de type PostStatus $post = new BlogPost( "Exemple brisé", "Un exemple brisé", "Soumis" );

La première instance fonctionne car son $Status est une valeur valide de l'énumération PostStatus. Dans le second cas, une chaîne simple est passée en tant que $Status, ce qui est interdit car la valeur doit être définie dans PostStatus.

Les cas d'énumération sont représentés sous forme de constantes sur l'objet enum. Cela signifie que vous pouvez les utiliser comme valeurs statiques et dans le cadre d'expressions constantes. Le constructeur BlogPost affiche un cas d'énumération utilisé comme valeur de paramètre par défaut, où $Status est automatiquement défini sur Draft lorsqu'aucune valeur n'est fournie par l'appelant.

Publicité

Vous pouvez accéder à toutes les valeurs disponibles dans une énumération en utilisant sa méthode cases :

PostStatus::cases(); //[PostStatus::Published, PostStatus::InReview, PostStatus::Draft]

Pure vs Backed Enums

L'énumération PostStatus ci-dessus est un pur enum. Il ne contient que des instructions de cas, sans données supplémentaires. PHP vous permet également d'attacher une valeur aux cas d'énumération, créant ainsi une énumération sauvegardée.

enum PostStatus : string { cas Publié = "S1"; case InReview = "S2"; case Brouillon = "S3"; }

Ici, l'énumération PostStatus a été modifiée pour créer une énumération sauvegardée. Le typehint dans la définition de l'énumération stipule que chaque cas a une valeur de chaîne qui lui est assignée. Dans cet exemple, nous supposons que chaque statut de publication nommé a un identifiant court associé. Il se peut que cet identifiant soit enregistré dans la base de données lorsque les publications sont persistantes.

Vous pouvez accéder aux valeurs sauvegardées via la propriété value sur les instances de cas :

classe BlogPostRepository {   fonction publique save(BlogPost $Post) : vide { $ceci -> insérer( "articles_de_blog", [ "titre" => $Post -> Titre, "contenu" => $Post -> Contenu, "statut" => $Post -> État -> valeur ] ); }   }   $post = nouveau BlogPost("Exemple", "Démo", PostStatus::Published); (nouveau BlogPostRepository()) -> économisez($post);

Cet exemple définirait la valeur du champ d'état persistant sur S1, en fonction de la version sauvegardée de l'énumération PostStatus indiquée ci-dessus.

Les énumérations sauvegardées n'acceptent que les chaînes et les entiers comme valeurs. Il n'est pas non plus possible d'utiliser le type d'union string|int. De plus, chaque cas a besoin d'une valeur unique – l'exemple suivant n'est pas autorisé :

enum PostStatus : string {   cas Publié = "S1"; case Brouillon = "S1";   } Publicité

PHP fournit une méthode utilitaire sur les énumérations pour créer une instance à partir d'une valeur sauvegardée :

//récupère l'article de blog précédent dans la base de données //le "statut" champ = S1 $status = PostStatus::from($record["status"]);

La méthode from() hydratera les instances des cas de valeur. Dans cet exemple, S1 est mappé vers le cas Publié et votre code reçoit une instance de PostStatus::Published.

from() renvoie une ValueError si la valeur d'entrée n'est pas valide ; dans les scénarios où vous savez que la valeur peut ne pas être utilisable, la méthode alternative tryFrom() peut être utilisée à la place. Cela renvoie null lorsqu'il n'y a pas de correspondance, au lieu de lancer l'erreur.

Ajout de méthodes aux énumérations

Comme les énumérations sont basées sur des classes, vous pouvez également leur ajouter des méthodes !

enum PostStatus {   cas Publié; cas Brouillon;   la fonction publique estPubliclyAccessible() : booléen { renvoie ($this instanceof self::Published); }   }

Cela vous permet de conserver un comportement spécifique à la casse dans votre énumération, au lieu de le dupliquer dans votre base de code.

Les énumérations peuvent également implémenter des interfaces :

enum PostStatus implémente PublicAccessGatable {   cas Publié; cas Brouillon;   la fonction publique estPubliclyAccessible() : booléen { renvoie ($this instanceof self::Published); }   }

Maintenant, vous pouvez transmettre une instance PostStatus à tout ce qui accepte un PublicAccessGatable :

classe UserAuthenticator {   la fonction devraitAllowAccess(PublicAccessGatable $Resource) : booléen { renvoie ($this -> Utilisateur -> isAdmin() || $Ressource -> est accessible au public()); }   }   $auth = new UserAuthenticator();   //récupère un article de blog à partir de la base de données si (!$auth -> shouldAllowAccess($post -> Statut)) { http_response_code(403); } Publicité

Il n'y a aucune restriction sur ce que vous pouvez faire avec les méthodes enum – ce sont des méthodes PHP normales, après tout – mais en général, vous vous attendez à ce qu'ils effectuent une sorte de comparaison avec le cas de l'instance, puis renvoient une valeur statique. Les énumérations peuvent utiliser des traits, vous pouvez donc extraire des méthodes existantes que vous avez également abstraites de cette manière.

Vous pouvez utiliser des méthodes publiques, protégées et privées dans les énumérations, bien que protégées et privées aient les mêmes effet. Les énumérations ne peuvent pas s'étendre les unes les autres, donc privé est effectivement redondant. Vous ne pouvez pas non plus ajouter de constructeur ou de destructeur. Les méthodes statiques sont prises en charge et peuvent être appelées sur la classe enum ou ses instances de cas.

Constantes

Les énumérations peuvent également avoir leurs propres constantes, soit en tant que valeurs littérales normales, soit en tant que référence à un cas d'énumération :

enum PostStatus {   cas Publié; cas Brouillon;   public const Live = self::Published; public const PlainConstant = "foobar";   }

Cela peut créer de la confusion car la même syntaxe est utilisée pour accéder aux cas (instances d'énumération) et aux constantes :

$published = PostStatus::Published ; $plain = PostStatus::PlainConstant;

Seul $published satisferait un indicateur de type PostStatus, car $plain fait référence à une valeur scalaire simple.

Quand utiliser les énumérations ?

Énumérations sont destinés aux occasions où vous avez besoin de flexibilité quant à la valeur qu'une variable peut prendre, mais uniquement parmi un ensemble prédéterminé de cas possibles.

Publicité

La classe d'article de blog qui est diffusée dans cet article est un exemple classique. Les messages ne peuvent être que dans l'un des ensembles d'états connus, mais PHP n'avait auparavant aucun moyen simple d'y parvenir.

Dans les anciennes versions, vous avez peut-être utilisé cette approche :

class PostStatus { const Publié = 0; const Ébauche = 1 ; }   classe BlogPost { fonction publique __construct( chaîne publique $Headline, public int $Status ) {} }   $post = nouveau BlogPost("Mon titre", PostStatus::Published);

Le problème ici est que $Status accepte en fait n'importe quel entier, donc l'appel suivant serait parfaitement valide :

$post = nouveau BlogPost("Mon titre", 9000);

De plus, BlogPost et PostStatus sont complètement détachés – il n'y a aucun moyen que quelqu'un lisant BlogPost puisse connaître la plage de valeurs que $Status accepte réellement. Bien que ces problèmes puissent être atténués en utilisant des astuces de type docblock appropriées ou un “fake enum” packages, ils ajoutent tous des couches supplémentaires autour d'un concept que d'autres langages de programmation simplifient.

L'ajout d'énumérations natives à PHP est une étape qui permet de compléter le système de types du langage. Vous pouvez enfin saisir les valeurs autorisées de manière à ce que tout le monde soit sur la même longueur d'onde. Si vous transmettez une valeur invalide, vous obtiendrez une erreur d'exécution. Votre IDE peut mieux vous aider à fournir des valeurs correctes, car il saura que $Status n'accepte que trois options, au lieu de “n'importe quel entier.”

Conclusion< /h2>

Les énumérations résolvent certains problèmes courants des développeurs lorsqu'ils travaillent en PHP. Ils permettent d'indiquer que les paramètres, les valeurs de retour et les propriétés doivent faire partie d'un ensemble d'options prédéterminées.

Les énumérations sont des entités de base de code flexibles que vous pouvez garder simples sous une forme pure, ou étendre avec des valeurs sauvegardées , les implémentations d'interface et les méthodes personnalisées. Les énumérations se comportent de la même manière que les objets normaux dans la plupart des cas et prennent en charge les fonctionnalités de classe telles que __call(), __invoke et ::class.

Publicité

Vous pouvez introspecter les énumérations avec la nouvelle fonction enum_exists() et ReflectionEnum Classe de réflexion. De plus, les énumérations implémentent deux nouvelles interfaces, UnitEnum (dans le cas des énumérations pures) et BackedEnum (pour les énumérations avec des valeurs sauvegardées). Ceux-ci peuvent être utilisés dans un code framework générique qui fonctionne avec n'importe quel enum. Les interfaces ne peuvent pas être implémentées manuellement par le code utilisateur.

Les Enums arriveront en PHP dans le cadre de la version 8.1 en novembre 2021. Ils sont déjà disponibles dans les dernières versions bêta. PHP 8.1 embarquera également plusieurs autres fonctionnalités pratiques, y compris les propriétés en lecture seule et les types d'intersection.