catch
Scopri come usare il costrutto "try...catch" in PHP per gestire errori ed eccezioni nel codice in modo efficace e sicuro.
La parola chiave catch in PHP
Quando il codice all'interno di un blocco try incontra un'eccezione — un object che segnala che qualcosa è andato storto — l'esecuzione si interrompe e PHP cerca un blocco catch corrispondente per gestirla. La parola chiave catch indica il tipo di eccezione che può gestire e assegna l'object lanciato a una variabile così da poterlo esaminare. Senza un catch, un'eccezione non gestita diventa un errore fatale e interrompe lo script.
Questa pagina illustra la sintassi di catch, come PHP sceglie quale blocco eseguire, come leggere i dettagli dall'eccezione catturata e i pattern comuni (catch multipli, tipi union, rilancio) che utilizzerai nel codice reale.
Sintassi
Un blocco catch segue sempre un blocco try. Dichiara un tipo di eccezione e una variabile che riceve l'object lanciato:
<?php
try {
// Code that may throw an exception
} catch (Exception $e) {
// Runs only if a matching exception is thrown above
echo $e->getMessage();
}PHP abbina un blocco catch quando l'object lanciato è un'istanza del tipo dichiarato. Poiché ogni eccezione built-in estende la classe base Exception (ed entrambe estendono l'interfaccia Throwable), catch (Exception $e) intercetta la maggior parte delle eccezioni. Catturare Throwable permette inoltre di gestire gli object Error come TypeError e DivisionByZeroError.
Puoi abbinare catch a un blocco finally per eseguire codice di pulizia indipendentemente dal fatto che si sia verificata un'eccezione.
Un esempio funzionante
La funzione seguente lancia un'eccezione quando le si chiede di dividere per zero. Il blocco catch intercetta quell'eccezione e la segnala invece di far crashare lo script:
<?php
function divide($numerator, $denominator)
{
if ($denominator == 0) {
throw new InvalidArgumentException("Division by zero.");
}
return $numerator / $denominator;
}
try {
echo divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage();
}
// Output: Error: Division by zero.Nota che lo script continua l'esecuzione dopo il catch — il controllo riprende dalla riga successiva alla struttura try/catch invece di interrompersi.
Leggere i dettagli dall'eccezione catturata
La variabile in una clausola catch ($e nell'esempio) è l'object exception stesso. Espone metodi che descrivono cosa è accaduto:
<?php
try {
throw new RuntimeException("Disk is full", 28);
} catch (RuntimeException $e) {
echo $e->getMessage(); // Disk is full
echo "\n";
echo $e->getCode(); // 28
echo "\n";
echo $e->getLine(); // 4 (line where it was thrown)
}| Metodo | Restituisce |
|---|---|
getMessage() | Il messaggio di errore leggibile |
getCode() | Il codice di errore intero passato al costruttore |
getFile() | Il file in cui l'eccezione è stata creata |
getLine() | Il numero di riga in cui è stata lanciata |
getTrace() | Lo stack trace come array |
getPrevious() | L'eccezione precedente (per eccezioni concatenate) |
Catturare più tipi di eccezione
Quando un blocco try può fallire in modi diversi, elenca più blocchi catch. PHP li prova dall'alto verso il basso ed esegue il primo che corrisponde, quindi ordina i tipi più specifici prima di quelli generali:
<?php
try {
// Code that may throw different exceptions
throw new InvalidArgumentException("bad input");
} catch (InvalidArgumentException $e) {
echo "Invalid argument: " . $e->getMessage();
} catch (RuntimeException $e) {
echo "Runtime problem: " . $e->getMessage();
} catch (Exception $e) {
echo "Something else: " . $e->getMessage();
}
// Output: Invalid argument: bad inputSe catch (Exception $e) venisse per primo, ingloberebbe tutto e i blocchi più specifici sottostanti non verrebbero mai eseguiti.
Union catch (PHP 7.1+)
Quando due tipi di eccezione diversi richiedono la stessa gestione, combinali con un pipe | invece di duplicare il blocco:
<?php
try {
throw new RuntimeException("connection reset");
} catch (InvalidArgumentException | RuntimeException $e) {
echo "Handled: " . $e->getMessage();
}
// Output: Handled: connection resetCatch non-capturing (PHP 8.0+)
Se non hai bisogno dell'object eccezione, puoi omettere completamente la variabile:
<?php
try {
throw new Exception("ignored details");
} catch (Exception) {
echo "An error occurred, retrying...";
}
// Output: An error occurred, retrying...Rilancio ed eccezioni concatenate
A volte un blocco catch dovrebbe registrare il problema e poi propagarlo — oppure avvolgere un'eccezione di basso livello in una più significativa. Passa l'originale come terzo argomento del costruttore per preservare la catena:
<?php
try {
try {
throw new RuntimeException("low-level failure");
} catch (RuntimeException $e) {
// Wrap and re-throw with context preserved
throw new Exception("High-level operation failed", 0, $e);
}
} catch (Exception $e) {
echo $e->getMessage(); // High-level operation failed
echo "\n";
echo $e->getPrevious()->getMessage(); // low-level failure
}Best practice
- Cattura il tipo più specifico che riesci a gestire. Un generico
catch (Throwable $e)può nascondere bug assorbendo errori di programmazione che avresti dovuto correggere. - Ordina dal più specifico al più generale. Le sottoclassi specifiche devono precedere i tipi padre.
- Non lasciare un
catchvuoto. Scartare silenziosamente un'eccezione rende i fallimenti invisibili; almeno registrala. - Lancia eccezioni, non flag di errore. Combina
catchconthrowcosì i chiamanti non possono ignorare accidentalmente i fallimenti. - Usa
finallyper la pulizia (chiusura di file, rilascio di lock) che deve avvenire sia nel percorso di successo che in quello di fallimento.
Argomenti correlati
- PHP
try— il blocco checatchprotegge - PHP
throw— lanciare un'eccezione - PHP
finally— codice di pulizia garantito - PHP
exception— l'object eccezione e i suoi metodi