try
Scopri come PHP try/catch/finally gestisce le eccezioni. Comprende blocchi catch multipli, tipi union, rilancio e insidie comuni.
La parola chiave try in PHP
La parola chiave try delimita un blocco di codice che potrebbe lanciare un'eccezione — un oggetto che segnala che qualcosa è andato storto e l'esecuzione normale non può continuare. Quando un'eccezione viene lanciata all'interno di un blocco try, PHP smette di eseguire il resto di quel blocco e cerca un blocco catch corrispondente per gestirla. Un blocco finally opzionale viene eseguito successivamente indipendentemente da ciò che è accaduto.
Questa pagina tratta la sintassi di try/catch/finally, come vengono abbinati più blocchi catch, come catturare più tipi di eccezione contemporaneamente, il rilancio delle eccezioni e le insidie più comuni. Se sei nuovo al concetto di lancio di errori, leggi prima Eccezioni in PHP.
Sintassi
try {
// Code that may throw an exception
} catch (ExceptionType $e) {
// Code that runs if an exception of ExceptionType (or a subclass) is thrown
} finally {
// Optional: always runs, whether or not an exception was thrown
}Un blocco try deve essere seguito da almeno un blocco catch, oppure da un blocco finally, oppure da entrambi — un try da solo è un errore di sintassi. La variabile in catch (ExceptionType $e) contiene l'oggetto eccezione lanciato, che si interroga con metodi come $e->getMessage().
Un primo esempio
La funzione seguente lancia un'eccezione quando le viene chiesto di dividere per zero. Il blocco try la chiama, il blocco catch segnala il problema e finally viene sempre eseguito:
<?php
function divide($dividend, $divisor)
{
if ($divisor == 0) {
throw new Exception("Cannot divide by zero.");
}
return $dividend / $divisor;
}
try {
$result = divide(10, 0);
echo $result; // skipped — divide() threw before returning
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . PHP_EOL;
} finally {
echo "Done." . PHP_EOL;
}Output:
Error: Cannot divide by zero.
Done.Si noti che echo $result; non viene mai eseguito: non appena divide(10, 0) lancia l'eccezione, il controllo passa direttamente al blocco catch. Il blocco finally viene eseguito dopo. Se invece si chiama divide(10, 2), non viene lanciata alcuna eccezione, il blocco try stampa 5 e finally stampa comunque Done..
Blocchi catch multipli
Un singolo try può essere seguito da diversi blocchi catch. PHP li controlla dall'alto verso il basso ed esegue il primo il cui tipo corrisponde all'eccezione lanciata (la corrispondenza include le sottoclassi). Elenca i tipi più specifici prima di quelli più generali — un catch (Exception $e) in testa ingloberebbe tutto ciò che segue.
<?php
try {
$value = "5";
if (!is_int($value)) {
throw new TypeError("Expected an integer.");
}
} catch (TypeError $e) {
echo "Type problem: " . $e->getMessage() . PHP_EOL;
} catch (Exception $e) {
echo "Other problem: " . $e->getMessage() . PHP_EOL;
}Output:
Type problem: Expected an integer.Catturare più tipi in un unico blocco
Quando due tipi di eccezione devono essere gestiti allo stesso modo, combinali con una barra verticale (|) — funzionalità aggiunta in PHP 7.1 — invece di duplicare il blocco:
<?php
try {
throw new RuntimeException("Network timed out.");
} catch (RuntimeException | LogicException $e) {
echo "Handled: " . $e->getMessage() . PHP_EOL;
}Output:
Handled: Network timed out.Come si comporta finally
Il blocco finally viene eseguito anche se il blocco try o catch esegue un return. Questo lo rende il posto giusto per le operazioni di pulizia — chiusura di file, rilascio di lock, rollback di una transazione — che devono avvenire in ogni caso:
<?php
function readConfig()
{
try {
return "config loaded";
} finally {
echo "Cleanup ran." . PHP_EOL;
}
}
echo readConfig() . PHP_EOL;Output:
Cleanup ran.
config loadedIl blocco finally viene eseguito prima che la funzione restituisca effettivamente il suo valore. Evita di usare return dentro finally: un return lì sovrascrive il valore restituito da try/catch e scarta silenziosamente qualsiasi eccezione che stava per essere lanciata.
Rilancio di un'eccezione
Un blocco catch può svolgere un lavoro parziale — registrare l'errore, aggiungere contesto — e poi rilanciare l'eccezione in modo che un chiamante di livello superiore possa decidere cosa fare. Usa throw $e; per rilanciare lo stesso oggetto:
<?php
try {
try {
throw new Exception("Disk full.");
} catch (Exception $e) {
echo "Logging: " . $e->getMessage() . PHP_EOL;
throw $e; // hand it to the outer handler
}
} catch (Exception $e) {
echo "Outer handler: " . $e->getMessage() . PHP_EOL;
}Output:
Logging: Disk full.
Outer handler: Disk full.Insidie comuni
tryha bisogno di un compagno. Un bloccotryda solo non viene analizzato correttamente — abbinalo ad almeno uncatcho unfinally.- Gli errori non sono tutti eccezioni. Molti avvisi di runtime (una variabile non definita, un
fopen()fallito) non vengono lanciati come eccezioni, quindicatchnon li intercetterà. Usaset_error_handler()oppure controlla i valori di ritorno per quei casi. Gli oggettiErrorfatali (comeTypeError) possono essere catturati perché implementanoThrowable. - Ordina i blocchi
catchdal più specifico al più generico. Uncatch (Exception $e)generico posto per primo nasconde tutti i blocchi successivi. - Non inglobare in silenzio. Un blocco
catchvuoto nasconde il fallimento; come minimo registra$e->getMessage()in modo che il problema sia visibile. finallypuò mascherare le eccezioni. Restituire dafinallyscarta sia il valore di ritorno ditrysia qualsiasi eccezione in corso.
Quando usare try?
Ricorri a try/catch quando un fallimento è eccezionale e il codice chiamante può ragionevolmente reagire ad esso: una connessione al database che si interrompe, un API che restituisce un errore, input utente non valido che vuoi rifiutare in modo pulito. Per il normale flusso di controllo (una chiave è presente in un array? una string è vuota?), usa i normali condizionali — le eccezioni sono per il percorso anomalo, non per la ramificazione quotidiana.
Correlati
catch— il blocco che gestisce un'eccezione lanciata.finally— codice che viene sempre eseguito dopotry/catch.throw— lancia tu stesso un'eccezione.- La classe Exception — il tipo base e i suoi metodi.
- Eccezioni in PHP — il quadro generale della gestione degli errori.
set_exception_handler()— cattura le eccezioni che sfuggono a ognitry.