Dans notre dernier épisode, nous avons discuté des améliorations à venir du système de type de PHP. Aujourd'hui, nous examinons une nouvelle construction qui rend la logique de branchement plus puissante.
PHP dispose d'une instruction switch
depuis la nuit des temps, basée sur la même construction en C. Vous l'avez sûrement déjà vue :
<?php switch ($var) { case 'a' : $message = "La variable était a." ; break ; case 'b' : $message = "La variable était c." ; break ; case 'c' : $message = "La variable était c." ; break ; default : $message = "La variable était autre chose." ; break ; } print $message ;
Bien qu'il soit efficace, le commutateur classique présente un certain nombre de limites. La plupart des nouveaux langages comme Go ou Rust ont opté pour des structures plus robustes et moins sujettes aux erreurs, qui portent des noms variés. Et maintenant, PHP en a une aussi.
Voici la fonction PHP match
. Contrairement à switch
, PHP match
est une expression. Cela signifie qu'elle s'évalue à une valeur, comme dans l'exemple suivant :
<?php $message = match($var) { 'a' => 'La variable était a', 'b' => 'La variable était b', 'c' => 'La variable était c', default => 'La variable était autre chose', } ; print $message ;
Il y a plusieurs choses à souligner ici :
switch
, chaque cas
est comparé avec l'égalité lâche ==
. Avec PHP match
, chaque branche est comparée avec l'égalité stricte, ===
. Cela signifie que les types doivent également correspondre.correspondance
est une expression unique. Il n'y a pas d'instructions sur plusieurs lignes, juste une expression unique qui est évaluée. Si vous avez besoin d'une logique complexe, faites-en une fonction ou une méthode que vous appelez.pause
.match
renvoie une valeur. C'est sa raison d'être.; de
fermeture est nécessaire à la toute fin, comme pour les définitions de fermetures.match
est exhaustif. Si $var
n'est pas ===
une des valeurs fournies et qu'il n'y a pas de valeur par défaut
, une erreur sera levée.Les branches dematch
peuvent également être composées et délimitées par des virgules pour un comportement de type "OR", comme ceci :
<?php echo match($operator) { '+', '-', '*', '/' => 'Basic arithmetic', '%' => 'Modulus', '!' => 'Negation', } ;
PHP match
a été présenté comme un commutateur
modernisé et plus utile, mais je ne suis pas sûr que ce soit exact. Je pense plutôt à match
comme un ternaire plus puissant.
Dans le passé, je me suis souvent retrouvé dans des cas binaires où une variable peut être assignée à l'une des deux valeurs en fonction d'une condition. La façon la plus simple d'écrire cela, je l'ai trouvée, est comme ceci :
<?php $display = $user->isAdmin() ? $user->name() . ' (admin)' : $user->name() . ' (muggle)' ;
Il s'agit d'un code tout à fait valide et très utile. Si la logique de la condition ou de l'une des branches est trop complexe pour être facilement lisible, c'est un indice que la logique devrait être remaniée dans sa propre fonction ou méthode. J'ai trouvé que c'était une très bonne heuristique pour des situations comme celle-ci, et que cela conduisait à un code très lisible, compact et testable.
Cela ne fonctionne que pour true/false
, cependant. match
, en revanche, fonctionne pour n'importe quel nombre d'options mais a les mêmes incitations à vous pousser vers un code propre et bien fait.
Si vous avez besoin de conditions plus complexes qu'une simple identité, vous pouvez utiliser match
on true
:
<?php $count = get_count() ; $size = match(true) { $count > 0 && $count <=10 => 'small', $count <=50 => 'medium', $count >50 => 'huge', } ;
Notez que puisqu'il n'y a pas de valeur par défaut
, une non correspondance (dans ce cas si $count
est 0 ou négatif) résultera en une erreur plutôt que d'assigner silencieusement à null et de passer à autre chose. C'est une bonne chose, car les erreurs ne peuvent pas se propager et polluer le code suivant.
Le RFC de l'expression match nous est offert par Ilija Tovilo.