PHP 10 juin 2024 8 min de lecture

PHP 8 : Switch vs Match, la révolution des expressions conditionnelles

Gabriel Janez

Gabriel Janez

Développeur Full-Stack PHP

PHP 8 a introduit l'expression match, une alternative moderne et élégante au bon vieux switch. Après l'avoir utilisée intensivement, je peux vous dire que c'est l'une des meilleures nouveautés de PHP 8. Voici pourquoi.

Le problème avec switch

Avant PHP 8, nous utilisions switch pour les conditions multiples. Mais soyons honnêtes, c'était verbeux et source d'erreurs :

// L'ancien switch - verbeux et dangereux
$statusText = '';

switch ($status) {
    case 1:
        $statusText = 'Brouillon';
        break;
    case 2:
        $statusText = 'En attente';
        break;
    case 3:
        $statusText = 'Publié';
        break;
    default:
        $statusText = 'Inconnu';
        break;
}

echo $statusText;

Les problèmes de switch :

  • Oubli du break : Si vous oubliez un break, le code "fall through" vers le case suivant (bug silencieux)
  • Comparaison lâche : switch utilise == et non ===, ce qui peut causer des surprises
  • Verbosité : Beaucoup de lignes pour une logique simple
  • Pas une expression : On ne peut pas directement assigner le résultat

L'arrivée de match en PHP 8

Voici le même code avec match :

// Le nouveau match - élégant et sûr
$statusText = match ($status) {
    1 => 'Brouillon',
    2 => 'En attente',
    3 => 'Publié',
    default => 'Inconnu',
};

echo $statusText;

C'est beau, non ? 4 lignes au lieu de 15, et surtout beaucoup plus sûr.

Les avantages de match

1. C'est une expression

match retourne une valeur, vous pouvez donc l'assigner directement :

// Assignation directe
$message = match ($httpCode) {
    200 => 'OK',
    201 => 'Created',
    400 => 'Bad Request',
    404 => 'Not Found',
    500 => 'Internal Server Error',
    default => 'Unknown Status',
};

// Utilisable partout où une expression est attendue
echo 'Status: ' . match ($status) {
    'active' => 'Actif',
    'inactive' => 'Inactif',
    default => 'N/A',
};

2. Comparaison stricte (===)

match utilise la comparaison stricte, fini les bugs subtils :

$value = '1'; // String

// switch utilise == (comparaison lâche)
switch ($value) {
    case 1: // int
        echo 'Switch: Trouvé !'; // ⚠️ Exécuté car '1' == 1
        break;
}

// match utilise === (comparaison stricte)
$result = match ($value) {
    1 => 'Match: Trouvé !',      // ❌ Non exécuté car '1' !== 1
    '1' => 'Match: Trouvé !',    // ✅ Exécuté car '1' === '1'
    default => 'Non trouvé',
};

3. Pas de fall-through

Plus besoin de break, chaque branche est isolée :

// Avec switch, oublier break = bug
switch ($role) {
    case 'admin':
        $permissions = 'all';
        // Oups, j'ai oublié break !
    case 'user':
        $permissions = 'read'; // Ce code s'exécute aussi pour admin 😱
        break;
}

// Avec match, impossible de se tromper
$permissions = match ($role) {
    'admin' => 'all',
    'user' => 'read',
    'guest' => 'none',
    default => 'none',
};

4. Valeurs multiples

Groupez plusieurs conditions avec une virgule :

$category = match ($extension) {
    'jpg', 'jpeg', 'png', 'gif', 'webp' => 'image',
    'mp4', 'avi', 'mkv', 'webm' => 'video',
    'mp3', 'wav', 'ogg', 'flac' => 'audio',
    'pdf', 'doc', 'docx', 'txt' => 'document',
    default => 'unknown',
};

5. Expressions dans les conditions

Contrairement à switch, vous pouvez utiliser des expressions :

$age = 25;

$category = match (true) {
    $age < 13 => 'enfant',
    $age < 20 => 'adolescent',
    $age < 60 => 'adulte',
    default => 'senior',
};

// Autre exemple avec des conditions complexes
$discount = match (true) {
    $user->isPremium() && $cart->total() > 100 => 20,
    $user->isPremium() => 10,
    $cart->total() > 200 => 5,
    default => 0,
};

Cas d'utilisation concrets

Mapping de valeurs

// Convertir un code HTTP en classe CSS
$alertClass = match (true) {
    $code >= 500 => 'alert-danger',
    $code >= 400 => 'alert-warning',
    $code >= 300 => 'alert-info',
    $code >= 200 => 'alert-success',
    default => 'alert-secondary',
};

Factory pattern simplifié

function createPaymentProcessor(string $type): PaymentProcessor
{
    return match ($type) {
        'stripe' => new StripeProcessor(),
        'paypal' => new PayPalProcessor(),
        'bank' => new BankTransferProcessor(),
        default => throw new InvalidArgumentException("Unknown payment type: $type"),
    };
}

Gestion des enums (PHP 8.1+)

enum Status: string {
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';
}

$label = match ($article->status) {
    Status::Draft => 'Brouillon',
    Status::Published => 'Publié',
    Status::Archived => 'Archivé',
};

Attention : match doit être exhaustif

Si aucune condition ne correspond et qu'il n'y a pas de default, PHP lance une UnhandledMatchError :

$result = match ($value) {
    1 => 'un',
    2 => 'deux',
    // Pas de default !
};

// Si $value = 3 → UnhandledMatchError: Unhandled match case 3

C'est en fait un avantage : vous êtes forcé de gérer tous les cas, ce qui évite les bugs silencieux.

Tableau récapitulatif

Caractéristiqueswitchmatch
TypeInstructionExpression ✓
ComparaisonLâche (==)Stricte (===) ✓
Fall-throughOui (break requis)Non ✓
Valeurs multiplesOui (cases empilés)Oui (virgule) ✓
Retourne une valeurNonOui ✓
Cas non géréSilencieuxException ✓

Conclusion

L'expression match est l'une des meilleures additions de PHP 8. Elle rend le code :

  • Plus concis : moins de lignes, plus de lisibilité
  • Plus sûr : comparaison stricte et exhaustivité forcée
  • Plus expressif : assignation directe du résultat

Mon conseil : utilisez match par défaut, et gardez switch uniquement si vous avez besoin du fall-through intentionnel (ce qui est rare).

Si vous n'êtes pas encore passé à PHP 8, c'est une raison de plus de faire la migration !

Tags

Bonnes pratiques match PHP PHP 8 switch Syntaxe

Partager

Articles similaires

Besoin d'aide sur votre projet ?

Discutons de vos besoins et trouvons ensemble la meilleure solution technique.

Me contacter