PHP case statement : guide complet avec exemples concrets

Dans cet article

  • Le switch/case en PHP compare une variable à plusieurs valeurs possibles avec une syntaxe plus lisible qu’une chaîne de if/elseif
  • L’oubli du break provoque un fall-through qui exécute tous les cas suivants, une erreur fréquente chez 70 % des débutants
  • Depuis PHP 8, l’expression match remplace avantageusement le switch dans les cas simples grâce à la comparaison stricte et au retour de valeur
  • On peut regrouper plusieurs valeurs dans un même case pour factoriser le code sans dupliquer la logique
  • Le bloc default est indispensable pour gérer les valeurs imprévues et sécuriser votre application
  • Je vous montre 7 exemples concrets tirés de projets WordPress et PHP natif pour maîtriser chaque variante

Quand je code en PHP depuis mes débuts il y a douze ans, le php case statement fait partie des structures que j’utilise quasiment chaque semaine. Que ce soit pour router une requête, gérer des rôles utilisateurs dans WordPress ou traiter un code de statut HTTP, le switch/case reste un outil fondamental du langage. Pourtant, je constate régulièrement que des développeurs, même expérimentés, tombent dans ses pièges classiques.

Dans ce guide, je vous partage tout ce que j’ai appris sur le terrain : la syntaxe complète, les erreurs à éviter et les cas d’usage concrets que je rencontre dans mes projets clients. Si vous cherchez à maîtriser le switch PHP ou à comprendre quand passer à match en PHP 8, vous êtes au bon endroit.

Syntaxe de base du switch/case en PHP

Le switch/case évalue une expression une seule fois, puis compare le résultat à chaque clause case. Dès qu’une correspondance est trouvée, le bloc de code associé s’exécute. Voici la structure minimale :

<?php
$role = 'editor';

switch ($role) {
    case 'admin':
        echo 'Accès complet au tableau de bord';
        break;
    case 'editor':
        echo 'Accès en édition aux contenus';
        break;
    case 'subscriber':
        echo 'Accès en lecture seule';
        break;
}

Quelques points essentiels à retenir sur cette syntaxe :

  • L’expression entre parenthèses après switch est évaluée une seule fois, contrairement à une chaîne de if/elseif qui réévalue la condition à chaque étape
  • Chaque case se termine par deux-points (:), pas par une accolade
  • La comparaison utilise l’opérateur == (égalité faible), ce qui signifie que 0 == 'texte' retourne true en PHP 7. C’est un piège que je détaillerai plus loin
  • Le break est techniquement optionnel, mais son absence a des conséquences importantes

PHP propose aussi une syntaxe alternative avec switch(): ... endswitch;, pratique quand vous mélangez PHP et HTML dans vos templates :

<?php switch ($page): ?>
    <?php case 'accueil': ?>
        <h1>Bienvenue sur le site</h1>
        <?php break; ?>
    <?php case 'contact': ?>
        <h1>Contactez-nous</h1>
        <?php break; ?>
<?php endswitch; ?>

J’utilise cette syntaxe dans certains thèmes WordPress quand le fichier mêle logique et affichage, mais je la réserve aux cas simples. Pour un projet structuré en PHP natif, je préfère la forme classique avec accolades.

Écrire du code PHP structuré avec des blocs switch/case bien indentés
Écrire du code PHP structuré avec des blocs switch/case bien indentés

Rôle du break et piège du fall-through

Le break interrompt l’exécution du switch et passe à l’instruction suivante après l’accolade fermante. Sans lui, PHP continue d’exécuter tous les blocs case suivants, peu importe si leurs valeurs correspondent ou non. C’est ce qu’on appelle le fall-through.

<?php
$statut = 'en_cours';

switch ($statut) {
    case 'en_cours':
        echo 'Commande en préparation. ';
        // Pas de break ici : fall-through volontaire
    case 'expediee':
        echo 'Un email de suivi a été envoyé. ';
        break;
    case 'livree':
        echo 'Commande terminée.';
        break;
}
// Affiche : "Commande en préparation. Un email de suivi a été envoyé."

Dans cet exemple, le fall-through est intentionnel : une commande en cours doit aussi déclencher l’email de suivi. Mais dans la majorité des cas, l’oubli du break est un bug. D’après mon expérience, c’est l’erreur numéro un que je corrige lors de revues de code.

Mon conseil : si vous utilisez un fall-through volontaire, ajoutez toujours un commentaire // fall-through intentionnel pour que le prochain développeur (ou vous-même dans six mois) comprenne que ce n’est pas un oubli. Les outils d’analyse statique comme PHPStan ou Psalm signaleront d’ailleurs un fall-through non commenté.

Case multiple : regrouper plusieurs valeurs

Quand plusieurs valeurs doivent déclencher le même traitement, on empile les case sans break entre eux. C’est l’équivalent d’un OR logique dans une condition if :

<?php
$extension = pathinfo($fichier, PATHINFO_EXTENSION);

switch ($extension) {
    case 'jpg':
    case 'jpeg':
    case 'png':
    case 'webp':
        $type = 'image';
        break;
    case 'pdf':
    case 'doc':
    case 'docx':
        $type = 'document';
        break;
    case 'mp4':
    case 'avi':
    case 'mov':
        $type = 'video';
        break;
    default:
        $type = 'autre';
        break;
}

Cette technique est particulièrement utile dans WordPress quand je gère les types de fichiers uploadés dans la médiathèque. Elle garde le code lisible même avec une dizaine de valeurs, là où un if ($ext == 'jpg' || $ext == 'jpeg' || $ext == 'png'...) deviendrait illisible.

Pour gérer un switch case avec plusieurs conditions plus complexes, on peut aussi combiner le switch avec true :

<?php
$age = 25;

switch (true) {
    case ($age < 18):
        echo 'Mineur';
        break;
    case ($age >= 18 && $age < 65):
        echo 'Adulte';
        break;
    case ($age >= 65):
        echo 'Senior';
        break;
}

Cette astuce fonctionne car chaque expression case est comparée à true. La première qui retourne true est exécutée. Je l’utilise rarement, mais c’est une alternative valable quand les conditions ne portent pas sur une simple égalité. Pour aller plus loin sur les variantes, consultez mon guide sur le case switch PHP.

Default : gérer les cas imprévus

Le bloc default s’exécute quand aucun case ne correspond à la valeur testée. Il joue le même rôle que le else final dans une chaîne if/elseif :

<?php
$methode_paiement = $_POST['paiement'] ?? '';

switch ($methode_paiement) {
    case 'carte':
        traiterCarteBancaire();
        break;
    case 'virement':
        traiterVirement();
        break;
    case 'paypal':
        traiterPaypal();
        break;
    default:
        error_log('Méthode de paiement inconnue : ' . $methode_paiement);
        afficherErreur('Veuillez sélectionner un mode de paiement valide.');
        break;
}

Je considère le default comme obligatoire dans tout switch/case en production. Voici pourquoi :

  • Il protège contre les valeurs inattendues provenant de formulaires, d’API ou de bases de données
  • Il permet de logger les anomalies pour le débogage
  • Il garantit que votre code a toujours un comportement défini, même face à une entrée imprévue

Le default peut être placé n’importe où dans le switch, mais par convention, on le met en dernier. Et même si c’est le dernier bloc, j’ajoute toujours le break par cohérence. Si un développeur ajoute un case après le default plus tard, le break évitera un fall-through accidentel.

Un diagramme de décision illustrant la logique conditionnelle en programmation
Un diagramme de décision illustrant la logique conditionnelle en programmation

Switch vs if/elseif : quand choisir l’un ou l’autre

C’est une question que mes clients juniors me posent souvent. La réponse dépend du contexte, mais voici comment je tranche en pratique :

Critèreswitch/caseif/elseif
ComparaisonÉgalité simple sur une seule variableConditions multiples, opérateurs variés
LisibilitéExcellente au-delà de 3 casMeilleure pour 2-3 conditions
Type de comparaisonÉgalité faible (==)Au choix (==, ===, <, >, etc.)
PerformanceLégèrement meilleur sur 10+ casÉquivalent sur peu de conditions
Conditions complexesNon adapté (sauf astuce switch(true))Parfaitement adapté
Retour de valeurNon (nécessite une variable)Non (nécessite une variable)
Fall-throughPossible (avantage ou piège)Impossible

Ma règle personnelle : si je compare une variable à plus de trois valeurs fixes, j’utilise switch/case. Si les conditions impliquent des plages de valeurs, des opérateurs différents ou plusieurs variables, je reste sur if/elseif. Cette règle simple m’a bien servi sur des centaines de projets.

En termes de performance, la différence est négligeable dans la plupart des cas. Le moteur Zend compile le switch en une table de sauts optimisée quand les valeurs sont des entiers consécutifs, mais en pratique, vous ne verrez jamais la différence sur un site web classique. Choisissez toujours la lisibilité en priorité.

Match en PHP 8 : l’évolution du switch

Depuis PHP 8.0, l’expression match offre une alternative moderne au switch/case. C’est devenu ma structure préférée pour les cas simples, et voici pourquoi :

<?php
// Avant (switch)
$prix_livraison = 0;
switch ($pays) {
    case 'FR':
        $prix_livraison = 5.90;
        break;
    case 'BE':
    case 'CH':
        $prix_livraison = 9.90;
        break;
    case 'DE':
    case 'ES':
        $prix_livraison = 12.90;
        break;
    default:
        $prix_livraison = 19.90;
        break;
}

// Après (match PHP 8)
$prix_livraison = match ($pays) {
    'FR' => 5.90,
    'BE', 'CH' => 9.90,
    'DE', 'ES' => 12.90,
    default => 19.90,
};

Les avantages de match par rapport au switch sont significatifs :

  • Comparaison stricte (===) : plus de piège avec les types. match(0) ne correspondra pas à 'texte'
  • Retour de valeur : match est une expression, pas une instruction. On peut l’assigner directement à une variable
  • Pas de break nécessaire : chaque branche retourne une seule valeur, impossible de tomber dans le fall-through
  • Syntaxe compacte : le même code prend deux fois moins de lignes
  • Exhaustivité : si aucune branche ne correspond et qu’il n’y a pas de default, PHP lance une UnhandledMatchError

Attention toutefois : match ne remplace pas tous les usages du switch. Si vous avez besoin d’exécuter plusieurs instructions par branche, ou si vous utilisez le fall-through intentionnellement, le switch reste nécessaire. Comme le précise la documentation officielle de PHP sur match, cette expression est conçue pour les cas où chaque branche produit une seule valeur.

Exemples concrets tirés de projets réels

Voici des extraits que j’utilise régulièrement dans mes projets WordPress et PHP. Chaque exemple illustre un usage différent du php case statement.

Routeur simple pour une API REST

<?php
$method = $_SERVER['REQUEST_METHOD'];
$endpoint = trim($_GET['action'] ?? '', '/');

switch ($method) {
    case 'GET':
        switch ($endpoint) {
            case 'articles':
                listerArticles();
                break;
            case 'categories':
                listerCategories();
                break;
            default:
                http_response_code(404);
                echo json_encode(['erreur' => 'Endpoint inconnu']);
                break;
        }
        break;
    case 'POST':
        creerArticle();
        break;
    case 'DELETE':
        supprimerArticle();
        break;
    default:
        http_response_code(405);
        echo json_encode(['erreur' => 'Méthode non autorisée']);
        break;
}

Cet exemple montre un switch imbriqué, une technique que j’emploie pour les micro-API sans framework. Chaque niveau gère une dimension différente (méthode HTTP, puis endpoint).

Gestion des rôles WordPress

<?php
function afficher_dashboard_personnalise() {
    $user = wp_get_current_user();
    $role = $user->roles[0] ?? 'subscriber';

    switch ($role) {
        case 'administrator':
            include get_template_directory() . '/partials/dashboard-admin.php';
            break;
        case 'shop_manager':
        case 'editor':
            include get_template_directory() . '/partials/dashboard-editeur.php';
            break;
        case 'author':
            include get_template_directory() . '/partials/dashboard-auteur.php';
            break;
        default:
            include get_template_directory() . '/partials/dashboard-abonne.php';
            break;
    }
}

Traitement de formulaire multi-étapes

<?php
$etape = (int) ($_POST['etape'] ?? 1);

switch ($etape) {
    case 1:
        validerInformationsPersonnelles($_POST);
        afficherEtape(2);
        break;
    case 2:
        validerAdresseLivraison($_POST);
        afficherEtape(3);
        break;
    case 3:
        validerPaiement($_POST);
        confirmerCommande();
        break;
    default:
        redirigerVers('/commande/etape-1');
        break;
}

Notez le cast (int) sur la valeur POST : cela évite les problèmes de comparaison faible entre chaînes et entiers. C’est une habitude que je recommande systématiquement quand la valeur comparée doit être un entier.

Un environnement de développement PHP moderne avec tests en cours d'exécution
Un environnement de développement PHP moderne avec tests en cours d’exécution

Erreurs fréquentes et bonnes pratiques

Après douze ans de pratique, voici les erreurs que je vois le plus souvent et mes recommandations pour les éviter :

1. La comparaison faible qui piège

<?php
// Piège classique en PHP 7
$valeur = 0;

switch ($valeur) {
    case 'texte':
        echo 'Ce cas est exécuté !';
        // Car 0 == 'texte' retourne true en PHP 7
        break;
    case 0:
        echo 'Jamais atteint...';
        break;
}

En PHP 8, ce comportement a été corrigé : la comparaison 0 == 'texte' retourne désormais false. Mais si vous maintenez du code PHP 7, castez explicitement vos valeurs avant le switch, ou passez à match qui utilise la comparaison stricte.

2. L’oubli du break dans un switch complexe

Plus le switch est long, plus le risque d’oublier un break augmente. Ma règle : toujours écrire le break immédiatement après avoir ouvert un case, puis remplir la logique entre les deux. C’est une habitude qui m’a évité des dizaines de bugs.

3. Le switch trop long

Si votre switch dépasse 15 à 20 cases, c’est un signal d’alarme. Envisagez plutôt un tableau associatif ou un pattern strategy :

<?php
// Au lieu d'un switch avec 20 cases
$actions = [
    'publier'    => fn() => publierArticle($id),
    'archiver'   => fn() => archiverArticle($id),
    'supprimer'  => fn() => supprimerArticle($id),
    'dupliquer'  => fn() => dupliquerArticle($id),
];

if (isset($actions[$action])) {
    $actions[$action]();
} else {
    throw new InvalidArgumentException("Action inconnue : $action");
}

Ce pattern avec un switch case en tableau associatif est plus extensible et plus facile à tester unitairement. Je l’utilise systématiquement dans mes projets dès que le nombre de cas dépasse une douzaine.

4. Négliger le typage

Toujours valider et typer les données avant de les passer au switch. Un $_GET['page'] non filtré peut contenir n’importe quoi. Utilisez filter_input() ou castez la valeur pour éviter les surprises. Comme le rappelle la documentation officielle du switch PHP, la comparaison faible est une source fréquente de bugs subtils.

Cas avancés : switch avec tableaux, fonctions et types

Le switch/case ne se limite pas aux comparaisons simples. Voici quelques techniques avancées que j’emploie dans des contextes spécifiques.

Switch avec le retour d’une fonction

<?php
switch (gettype($donnee)) {
    case 'integer':
    case 'double':
        $resultat = formaterNombre($donnee);
        break;
    case 'string':
        $resultat = htmlspecialchars($donnee, ENT_QUOTES, 'UTF-8');
        break;
    case 'array':
        $resultat = implode(', ', array_map('htmlspecialchars', $donnee));
        break;
    case 'boolean':
        $resultat = $donnee ? 'Oui' : 'Non';
        break;
    default:
        $resultat = '(type non géré)';
        break;
}

L’expression passée au switch peut être n’importe quel appel de fonction, opération ou même une expression ternaire. PHP l’évalue une seule fois, ce qui est plus performant que de répéter gettype($donnee) dans chaque condition d’un if/elseif.

Switch et constantes de classe

<?php
class CommandeStatut {
    const EN_ATTENTE = 'pending';
    const VALIDEE    = 'confirmed';
    const EXPEDIEE   = 'shipped';
    const LIVREE     = 'delivered';
    const ANNULEE    = 'cancelled';
}

switch ($commande->statut) {
    case CommandeStatut::EN_ATTENTE:
        envoyerConfirmation($commande);
        break;
    case CommandeStatut::VALIDEE:
        preparerExpedition($commande);
        break;
    case CommandeStatut::EXPEDIEE:
        envoyerTracking($commande);
        break;
    case CommandeStatut::LIVREE:
        demanderAvis($commande);
        break;
    case CommandeStatut::ANNULEE:
        rembourser($commande);
        break;
    default:
        error_log('Statut inconnu : ' . $commande->statut);
        break;
}

Utiliser des constantes de classe plutôt que des chaînes en dur rend le switch résistant aux fautes de frappe. Votre IDE détectera une constante inexistante, mais pas une chaîne mal orthographiée. Si vous travaillez en PHP 8.1+, les enums remplacent avantageusement cette approche.

Combinaison switch et return dans une fonction

<?php
function getLibelleStatutHTTP(int $code): string {
    switch ($code) {
        case 200: return 'OK';
        case 301: return 'Redirection permanente';
        case 404: return 'Page non trouvée';
        case 500: return 'Erreur serveur interne';
        default:  return 'Code inconnu';
    }
}

Quand chaque case ne fait que retourner une valeur, le return remplace le break puisqu’il quitte la fonction entière. C’est une syntaxe compacte que j’apprécie pour les fonctions de mapping. En PHP 8, ce cas précis se réécrit encore mieux avec match :

<?php
function getLibelleStatutHTTP(int $code): string {
    return match ($code) {
        200 => 'OK',
        301 => 'Redirection permanente',
        404 => 'Page non trouvée',
        500 => 'Erreur serveur interne',
        default => 'Code inconnu',
    };
}

La manipulation de chaînes est un sujet connexe : si vous travaillez aussi en JavaScript, vous pouvez consulter mon article sur splice en JavaScript ou sur trimEnd JavaScript pour des comparaisons intéressantes entre les deux langages.

À retenir

  • Ajoutez systématiquement un break après chaque case, sauf fall-through documenté par un commentaire
  • Incluez toujours un bloc default pour capturer les valeurs imprévues et loguer les anomalies
  • Passez à match en PHP 8 quand chaque branche retourne une simple valeur : comparaison stricte et code plus concis
  • Au-delà de 12-15 cases, remplacez le switch par un tableau associatif ou un pattern strategy
  • Castez les données utilisateur avant le switch pour éviter les pièges de la comparaison faible

Questions fréquentes

Quelle est la différence entre switch et match en PHP ?

Le switch utilise la comparaison faible (==), nécessite des break et exécute des instructions. Le match, disponible depuis PHP 8, utilise la comparaison stricte (===), retourne directement une valeur et ne nécessite pas de break. Match est plus sûr et plus concis pour les cas simples, mais switch reste nécessaire pour les traitements multi-instructions.

Peut-on utiliser plusieurs valeurs dans un seul case PHP ?

Oui, en empilant les case sans break entre eux : case 'a': case 'b': case 'c': // code break;. Avec match en PHP 8, c’est encore plus simple : 'a', 'b', 'c' => resultat. Les deux approches exécutent le même bloc pour plusieurs valeurs.

Le default est-il obligatoire dans un switch PHP ?

Non, PHP ne l’impose pas syntaxiquement. Cependant, en pratique, je le considère obligatoire dans tout code de production. Sans default, une valeur imprévue passera silencieusement sans aucun traitement, ce qui rend le débogage très difficile. Ajoutez au minimum un log d’erreur dans le bloc default.

Pourquoi mon switch PHP exécute plusieurs cases à la suite ?

C’est le fall-through : vous avez probablement oublié un break à la fin d’un case. Sans break, PHP continue d’exécuter tous les blocs suivants jusqu’au prochain break ou à la fin du switch. Vérifiez que chaque case se termine par un break ou un return.

Le switch PHP est-il plus rapide que if/elseif ?

La différence de performance est négligeable dans la plupart des cas. Le switch peut être légèrement plus rapide avec de nombreux cas car l’expression est évaluée une seule fois, mais l’écart se mesure en microsecondes. Choisissez toujours la structure la plus lisible pour votre situation plutôt que d’optimiser prématurément.

Comment utiliser un switch avec un tableau en PHP ?

Vous ne pouvez pas comparer directement un tableau dans un case. Utilisez plutôt in_array() dans un if, ou testez une propriété spécifique du tableau dans le switch : switch($tableau['type']). Vous pouvez aussi utiliser un tableau associatif comme alternative au switch pour mapper des clés à des actions.

Nathan Morel
Nathan Morel

Nathan Morel est développeur web freelance depuis 12 ans dans la Loire. Spécialisé WordPress et solutions sur mesure, il a accompagné plus de 200 PME et partage son expérience technique et entrepreneuriale sur NA Web.

Un projet web ? Discutons-en.

Diagnostic gratuit et devis sous 24h.

Me contacter

Votre site est lent ?

Optimiser mon site