PHP moderno: usare le espressioni <strong>match</strong> per scrivere condizioni più sicure

by theArchitect
SHARE
PHP moderno: usare le espressioni <strong>match</strong> per scrivere condizioni più sicure
© Guida-HTML5.it

Introduzione

Tra le novità più utili introdotte nelle versioni moderne di PHP troviamo l’espressione match, disponibile a partire da PHP 8.0. È una forma evoluta di switch che permette di confrontare un valore con diverse alternative in modo più compatto, leggibile e sicuro.

In un’applicazione reale, match può essere utilizzato per trasformare uno stato interno in un’etichetta leggibile, scegliere una strategia di elaborazione, determinare il codice HTTP da restituire oppure selezionare un messaggio in base al ruolo dell’utente.

La differenza principale rispetto a switch è che match è un’espressione: produce direttamente un valore e può quindi essere assegnata a una variabile o restituita da una funzione. Inoltre utilizza confronti stretti, equivalenti a ===, e non richiede la parola chiave break.

Codice completo

<?php

declare(strict_types=1);

/**
 * Converte lo stato interno di un ordine
 * in un testo destinato all´interfaccia utente.
 */
function descriviOrdine(string $stato): string
{
    return match ($stato) {
        ´nuovo´ => ´L’ordine è stato ricevuto.´,
        ´pagato´ => ´Il pagamento è stato confermato.´,
        ´spedito´ => ´L’ordine è stato affidato al corriere.´,
        ´consegnato´ => ´L’ordine è stato consegnato.´,
        ´annullato´ => ´L’ordine è stato annullato.´,
        default => ´Stato ordine non riconosciuto.´,
    };
}

/**
 * Determina il codice HTTP in base allo stato dell´ordine.
 */
function codiceHttpOrdine(string $stato): int
{
    return match ($stato) {
        ´nuovo´, ´pagato´, ´spedito´, ´consegnato´ => 200,
        ´annullato´ => 410,
        default => 404,
    };
}

/**
 * Determina una priorità usando condizioni generiche.
 */
function prioritaOrdine(int $totale, bool $clientePremium): string
{
    return match (true) {
        $clientePremium && $totale >= 500 => ´alta´,
        $clientePremium || $totale >= 200 => ´media´,
        default => ´normale´,
    };
}

$stato = ´spedito´;
$totale = 275;
$clientePremium = true;

echo descriviOrdine($stato) . PHP_EOL;
echo ´Codice HTTP: ´ . codiceHttpOrdine($stato) . PHP_EOL;
echo ´Priorità: ´ . prioritaOrdine($totale, $clientePremium) . PHP_EOL;

Spiegazione

Un confronto diretto con un valore

La sintassi di base è la seguente:

$risultato = match ($valore) {
    ´prima-opzione´ => ´Risultato A´,
    ´seconda-opzione´ => ´Risultato B´,
    default => ´Risultato predefinito´,
};

PHP valuta l’espressione tra parentesi e confronta il risultato con ciascun caso. Il confronto è rigoroso: il valore e il tipo devono corrispondere. Per esempio, il valore intero 1 non viene considerato uguale alla stringa ´1´.

$tipo = 1;

$risultato = match ($tipo) {
    ´1´ => ´Stringa´,
    1 => ´Intero´,
    default => ´Altro´,
};

echo $risultato; // Intero

Questa caratteristica riduce gli errori causati dalle conversioni automatiche dei tipi, frequenti in alcuni confronti con il vecchio switch.

Più valori nella stessa alternativa

È possibile associare più valori allo stesso risultato separandoli con una virgola. Nel metodo codiceHttpOrdine(), per esempio, diversi stati validi restituiscono il codice 200:

return match ($stato) {
    ´nuovo´, ´pagato´, ´spedito´, ´consegnato´ => 200,
    ´annullato´ => 410,
    default => 404,
};

Questa forma evita di duplicare il medesimo risultato in più rami e rende evidente la relazione tra gli stati.

Il caso default

Il ramo default gestisce tutti i valori che non corrispondono ai casi elencati. È consigliabile inserirlo quando un valore sconosciuto deve essere trattato in modo controllato, ad esempio mostrando un messaggio generico o restituendo un codice HTTP specifico.

Se nessun caso corrisponde e non è presente default, PHP genera un’eccezione UnhandledMatchError. Questo comportamento può essere utile quando l’assenza di un caso rappresenta un errore di programmazione che non deve essere ignorato.

Usare match (true)

Un modello interessante è match (true). In questo caso ogni alternativa è un’espressione booleana. La prima condizione che restituisce true determina il risultato. È una soluzione leggibile per sostituire catene di if e elseif, soprattutto quando le condizioni dipendono da più variabili.

L’ordine dei casi è importante: il primo caso compatibile viene scelto. Per questo motivo le condizioni più specifiche dovrebbero essere scritte prima di quelle più generiche.

Best practice

  • Usa match per produrre un valore: se devi solo eseguire molte istruzioni indipendenti, una catena di if può essere più adatta.
  • Preferisci confronti espliciti: la natura rigorosa di match aiuta a evitare ambiguità tra stringhe, interi e booleani.
  • Valuta attentamente default: inseriscilo quando vuoi gestire valori inattesi; omettilo se preferisci ricevere un errore immediato durante lo sviluppo.
  • Non inserire troppa logica nei rami: se il risultato richiede molti calcoli, sposta il comportamento in funzioni dedicate.
  • Ordina correttamente le condizioni: con match (true), una condizione generale scritta troppo presto potrebbe rendere irraggiungibili quelle successive.
  • Usa declare(strict_types=1): il controllo rigoroso dei tipi rende il comportamento dell’applicazione più prevedibile.
  • Verifica la versione PHP: il codice richiede PHP 8.0 o una versione successiva. In un progetto condiviso, specifica il requisito nel file composer.json.

Riepilogo

L’espressione match è una delle funzionalità più pratiche del PHP moderno. Permette di associare in modo chiaro un valore a uno o più risultati, usa confronti stretti, restituisce direttamente un’espressione e non richiede break.

Rispetto a switch, riduce il rischio di errori causati dal fall-through e rende più semplice leggere funzioni che trasformano stati, ruoli o categorie. Con match (true) può inoltre rappresentare condizioni ordinate, mantenendo una struttura compatta e facile da testare.

Approfondisci con risorse ufficiali

SHARE