W3docs

Capire le Eccezioni PHP

In PHP, le eccezioni gestiscono errori imprevisti e problemi a runtime. Scopri come usare throw, catch, finally e classi personalizzate.

Un'eccezione è un oggetto che rappresenta un errore o una condizione inaspettata che interrompe il normale flusso del programma. Invece di restituire un codice di errore che il chiamante potrebbe dimenticare di verificare, il codice "lancia" un'eccezione; il runtime risale lo stack delle chiamate finché non trova un blocco catch corrispondente. Se nessun blocco la intercetta, lo script si interrompe con un errore fatale.

Questo capitolo spiega come lanciare e intercettare le eccezioni, i metodi esposti da ogni eccezione (getMessage(), getCode(), getLine(), getFile()), il blocco finally, i blocchi catch multipli, le classi di eccezione personalizzate e la differenza tra Exception e Error.

Cos'è un'Eccezione PHP?

Un'eccezione PHP è un oggetto che discende dalla classe built-in Exception (o, più in generale, dall'interfaccia Throwable). Quando qualcosa va storto — un file mancante, un argomento non valido, una connessione al database fallita — si crea uno di questi oggetti e lo si lancia con throw. Il lancio interrompe immediatamente il percorso di esecuzione corrente e passa il controllo al gestore più vicino.

Usa un'eccezione quando una funzione non può continuare in modo significativo e il chiamante è il posto giusto per decidere cosa fare dopo. Non usarle per il normale flusso di controllo (una normale ricerca "utente non trovato" è meglio espressa con un valore di ritorno).

Lanciare un'Eccezione

La parola chiave throw solleva un'eccezione, seguita da una nuova istanza di una classe di eccezione. Il costruttore accetta un messaggio opzionale, un codice intero e un'eccezione precedente (per il concatenamento):

<?php

function divide(int $a, int $b): float
{
    if ($b === 0) {
        throw new InvalidArgumentException('Division by zero is not allowed.');
    }
    return $a / $b;
}

try {
    echo divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo 'Error: ' . $e->getMessage();
}
?>

Output:

Error: Division by zero is not allowed.

Il codice all'interno di try viene eseguito normalmente finché non si attiva throw. Da quel momento in poi il resto del blocco try viene saltato e viene eseguito il blocco catch corrispondente.

Gestire le Eccezioni con try / catch

Si racchiude il codice che potrebbe fallire in un blocco try e si gestisce il fallimento in un blocco catch. La variabile in catch (qui $e) contiene l'oggetto eccezione, che espone diversi metodi di sola lettura:

MetodoRestituisce
getMessage()Il messaggio leggibile dall'utente
getCode()Il codice intero passato al costruttore
getLine()La riga dove è stata lanciata l'eccezione
getFile()Il file in cui è stata lanciata
getPrevious()L'eccezione "precedente" concatenata, se presente
getTraceAsString()Lo stack trace come stringa
<?php

try {
    throw new Exception('Something failed', 42);
} catch (Exception $e) {
    echo 'Message: ' . $e->getMessage() . PHP_EOL;
    echo 'Code: ' . $e->getCode() . PHP_EOL;
}
?>

Output:

Message: Something failed
Code: 42

Intercettare Più Tipi di Eccezione

Un singolo blocco try può avere più blocchi catch. PHP li verifica dall'alto verso il basso ed esegue il primo il cui tipo corrisponde. Da PHP 7.1 è possibile intercettare più tipi non correlati in un unico blocco usando l'operatore pipe (|):

<?php

try {
    throw new RuntimeException('Network is down');
} catch (InvalidArgumentException $e) {
    echo 'Bad argument: ' . $e->getMessage();
} catch (RuntimeException | LogicException $e) {
    echo 'Runtime/logic problem: ' . $e->getMessage();
}
?>

Output:

Runtime/logic problem: Network is down

L'ordine è importante: elenca i tipi di eccezione più specifici prima delle loro classi padre, altrimenti il catch generico intercetta tutto per primo.

Il Blocco finally

Il blocco finally è opzionale ma utile. Il suo codice viene sempre eseguito — che venga lanciata o meno un'eccezione, e anche se il blocco try o catch esegue un return. Questo lo rende il posto giusto per operazioni di pulizia come la chiusura di un file o il rilascio di un lock:

<?php

try {
    echo 'Open resource' . PHP_EOL;
    throw new Exception('Boom');
} catch (Exception $e) {
    echo 'Caught: ' . $e->getMessage() . PHP_EOL;
} finally {
    echo 'Cleanup always runs' . PHP_EOL;
}
?>

Output:

Open resource
Caught: Boom
Cleanup always runs

Classi di Eccezione Personalizzate

Oltre ai tipi built-in puoi definire le tue classi di eccezione estendendo Exception. Una classe personalizzata ti permette di portare dati aggiuntivi (come un valore che ha causato il fallimento) e consente ai chiamanti di intercettare il tuo tipo di errore specifico senza accidentalmente intercettare quelli non correlati:

<?php

class InsufficientFundsException extends Exception
{
    private float $shortfall;

    public function __construct(float $shortfall)
    {
        $this->shortfall = $shortfall;
        parent::__construct("Short by $shortfall");
    }

    public function getShortfall(): float
    {
        return $this->shortfall;
    }
}

try {
    throw new InsufficientFundsException(25.5);
} catch (InsufficientFundsException $e) {
    echo $e->getMessage() . PHP_EOL;
    echo 'Need ' . $e->getShortfall() . ' more.';
}
?>

Output:

Short by 25.5
Need 25.5 more.

PHP fornisce anche una famiglia di eccezioni SPL già pronte — InvalidArgumentException, RuntimeException, LengthException e altre — quindi spesso non è necessario inventarne di proprie.

Exception vs. Error

Da PHP 7, i fallimenti interni del motore (come un errore di tipo o la chiamata a un metodo non definito) vengono lanciati come oggetti Error, non Exception. Entrambi implementano l'interfaccia Throwable. Un semplice catch (Exception $e) non intercetterà un Error. Per gestire entrambi, intercetta l'interfaccia:

<?php

try {
    $result = 10 % 0; // throws a DivisionByZeroError
} catch (Throwable $e) {
    echo get_class($e) . ': ' . $e->getMessage();
}
?>

Output:

DivisionByZeroError: Modulo by zero

Come regola generale, riserva Exception per i problemi da cui la tua applicazione può riprendersi, e lascia che Error rappresenti i bug da correggere piuttosto che da intercettare.

Argomenti Correlati

Conclusione

Le eccezioni offrono a PHP un modo strutturato per gestire i fallimenti: una funzione lancia con throw quando non può continuare, e il chiamante intercetta con catch per recuperare, registrare o rilanciare. Combina try, catch e finally per separare il percorso normale dalla gestione degli errori e dalla pulizia, usa classi personalizzate per modellare i fallimenti del tuo dominio e ricorda che i problemi a livello di motore arrivano come Error (intercettabili tramite Throwable). Applicare questi pattern nei tuoi progetti renderà il codice molto più robusto.

Pratica

Pratica
Cosa è vero riguardo alle Eccezioni PHP in base alle informazioni sull'URL fornito?
Cosa è vero riguardo alle Eccezioni PHP in base alle informazioni sull'URL fornito?
Was this page helpful?