Accueil >PHP >Migrer vers PHP 8 >match au lieu de switch

match au lieu de switch

L’expression match de PHP 8.0 renvoie une valeur, compare de façon stricte et n’oublie jamais le break. Quand l’utiliser au lieu de switch, comment écrire des intervalles par match(true) et ce qui se passe quand aucune branche ne correspond.

Syntaxe

Un switch typique, qui selon la valeur ne fait que choisir une autre valeur :

$code = 404;
switch($code)
  {
    case 200:
    case 201:
      $text = "ok";
      break;
    case 404:
      $text = "page introuvable";
      break;
    default:
      $text = "autre statut";
  }
echo $text;
page introuvable

La même chose avec match :

$code = 404;
$text = match($code)
  {
    200, 201 => "ok",
    404 => "page introuvable",
    default => "autre statut",
  };
echo $text;
page introuvable

Différences avec switch :

  • match est une expression – elle renvoie une valeur que vous pouvez aussitôt affecter, afficher ou renvoyer depuis une fonction.
  • Elle compare de façon stricte (===), switch de façon souple (==).
  • Il n’y a pas de passage à la branche suivante, un break manquant ne peut donc pas provoquer d’erreur. Plusieurs valeurs pour une branche se séparent par une virgule.
  • Une branche contient une seule expression. Pour plusieurs instructions, appelez une fonction.
  • Si aucune branche ne correspond et que default manque, elle lève l’exception UnhandledMatchError. switch ne fait rien dans ce cas.
  • Les branches sont vérifiées dans l’ordre à partir du haut, et l’évaluation s’arrête à la première correspondance.

Comparaison stricte

Les valeurs des formulaires et de l’adresse sont toujours des chaînes. Avec match, vous devez y faire attention :

$page = "1";   // par exemple depuis $_GET
switch($page)
  {
    case 1:
      echo "switch : première page\n";
      break;
    default:
      echo "switch : autre page\n";
  }
echo match($page)
  {
    1 => "match : première page",
    default => "match : autre page",
  };
switch : première page
match : autre page

La chaîne "1" n’est pas strictement égale au nombre 1. Convertissez la valeur auparavant : match((int) $page).

Quand aucune branche ne correspond

$status = "cancelled";
try
  {
    echo match($status)
      {
        "new" => "Nouvelle commande",
        "shipped" => "Expédiée",
      };
  }
catch(\UnhandledMatchError $e)
  {
    echo $e->getMessage();
  }
Unhandled match case 'cancelled'

Une exception non traitée arrête le script. C’est un avantage : une branche manquante se révèle tout de suite, et pas seulement sous forme d’un mauvais résultat quelque part plus loin. Si une valeur inconnue peut venir de l’extérieur, écrivez une branche default ou levez-y votre propre exception – throw est une expression en PHP 8, elle tient donc dans une branche :

function statusName(string $status): string
  {
    return match($status)
      {
        "new" => "Nouvelle commande",
        "shipped" => "Expédiée",
        default => throw new InvalidArgumentException("Statut inconnu : ".$status),
      };
  }
echo statusName("shipped");
Expédiée

Intervalles : match(true)

Si, au lieu de comparer une seule valeur, il faut évaluer des conditions, on utilise match(true). C’est la première branche dont la condition est remplie qui est choisie :

$temperature = 23;
echo match(true)
  {
    $temperature < 0 => "glacial",
    $temperature < 20 => "froid",
    $temperature < 30 => "doux",
    default => "chaud",
  };
doux

Les conditions doivent vraiment renvoyer true. Une expression qui renvoie une autre valeur « vraie » (par exemple preg_match() renvoie 1) n’est pas strictement égale à true – convertissez une telle condition par (bool) ou écrivez-la sous forme de comparaison.

Quand rester sur switch

switch a du sens quand les branches exécutent plusieurs instructions et ne renvoient rien, ou quand le passage à la branche suivante est voulu. En PHP 7.4, un match simple peut être remplacé par un tableau :

$code = 404;
$names = [200 => "ok", 201 => "ok", 404 => "page introuvable"];
echo $names[$code] ?? "autre statut";
page introuvable

Le tableau convertit toutefois les chaînes numériques en nombres, si bien que $names["404"] trouve le même élément que $names[404] – la comparaison n’est pas stricte ici. C’est avec les énumérations que match s’accorde le mieux, voir Énumérations (enum).

Articles connexes :
Énumérations (enum)
Changements de PHP 8 qui cassent l’ancien code
Arguments nommés et opérateur nullsafe