Le eccezioni forniscono un meccanismo unificato per la gestione degli errori in modo estensibile, manutenibile, ed object-oriented.
L’idea di base è che il codice è eseguito all’interno di un blocco try
, con un codice simile al seguente:
try { // tuo codice }
Se qualcosa va storto all’interno del blocco try
, si può creare quella che viene chiamata un’eccezione.
Alcuni linguaggi, come Java, generano in certi casi, automaticamente delle eccezioni per noi.
In PHP, le eccezioni devono essere generate manualmente. Si genera un’eccezione come segue:
throw new Exception('messaggio', codice);
La parola chiave throw
innesca il meccanismo di gestione delle eccezioni. Si tratta di un costrutto del linguaggio piuttosto che di una funzione.
Si aspetta di ricevere un oggetto. Nel caso più semplice, è possibile creare un’istanza della classe interna Exception
, come fatto nell’esempio.
Il costruttore della classe prende 2 parametri, un messaggio ed un codice che sarebbero rispettivamente il messaggio ed il codice di errore. Entrambi i parametri sono opzionali.
Infine, sotto il tuo blocco try
, è necessario almeno un blocco catch
.
Un blocco catch
assomiglia a questo:
catch (Exception $e) { // gestione dell'eccezione }
L’oggetto passato al blocco catch
è quello passato all’istruzione throw
che ha generato l’eccezione.
L’eccezione può essere di qualsiasi tipo, ma è buona norma utilizzare le istanze della classe Exception
o casi di eccezioni personalizzate definite dall’utente che ereditano dalla classe Exception
.
Quando viene sollevata un’eccezione, PHP cerca un blocco catch corrispondente. Se si dispone di più di un blocco catch, gli oggetti passati a ciascuno dovrebbero essere di tipi diversi in modo che PHP può capire quale blocco catch usare.
Un altro punto da notare è che si può sollevare ulteriori eccezioni all’interno di un blocco catch.
Un semplice esempio di gestione delle eccezioni:
try { throw new Exception("Si è verifivato un'errore imprevedibile!", 42); } catch (Exception $e) { echo "Exception ". $e->getCode(). ": ". $e->getMessage()."". " in ". $e->getFile(). " on line ". $e->getLine(). ""; }
La classe Exception
Come discusso prima il costruttore della classe Exception
accetta 2 parametri, il messaggio ed il codice di errore.
In aggiunta al costruttore la classe ha i seguenti metodi:
getCode()
->Ritorna il codice passato al costruttoregetMessage()
-> Ritorna il messaggio passato al costruttoregetFile
-> Ritorna il full path del file in cui l’eccezione è stata sollevatagetLine
-> Ritorna il numero di linea in cui l’eccezione viene sollevatagetTrace
-> Ritorna un array contenente un backtrace dove l’eccezione è stata sollevatagetTraceAsString
-> Ritorna le stesse info di getTrace formattate come stringa__toString
-> Permette di fare un’echo
di un oggettoException
, dando tutte le info dei metodi di sopra. es:echo $e
PS: backtrace mostra quali funzioni erano in esecuzione al momento del sollevamento dell’eccezione.
Eccezioni definite dall’utente
Invece di istanziare e passare un’istanza della classe Exception
di base, possiamo passare un oggetto simile.
In molti casi estenderemo la classe Exception
per crearne una personalizzata.
Il manuale di PHP fornisce uno scheletro della classe Exception
attraverso il quale possiamo capire come estenderla.
Si noti che questo non è il codice vero e proprio ma rappresenta ciò che ci si può aspettare di ereditare:
Exception { /* Properties */ protected string $message ; protected int $code ; protected string $file ; protected int $line ; /* Methods */ public __construct ([ string $message = "" [, int $code = 0 [, Exception $previous = NULL ]]] ) final public string getMessage ( void ) final public Exception getPrevious ( void ) final public mixed getCode ( void ) final public string getFile ( void ) final public int getLine ( void ) final public array getTrace ( void ) final public string getTraceAsString ( void ) public string __toString ( void ) final private void __clone ( void ) }
Da notare che la maggior parte dei metodi pubblici sono final
. Ciò significa che non possono essere sovrascritti.
È possibile creare sottoclassi, ma non è possibile modificare il comportamento dei metodi di base. Notare che invece è possibile eseguire l’override della funzione __toString()
.
È inoltre possibile aggiungere dei metodi personali. Vediamo un esempio in cui vado e crearmi la mia funzione _toString
personalizzata:
class myException extends Exception { function __toString() { return "
Exception ".$this->getCode()." : ".$this->getMessage().""." in ".$this->getFile()." on line ".$this->getLine()." |
Potrò poi tranquillamente usare la mia nuova classe quando voglio generare un’eccezione così:
try { throw new myException("A terrible error has occurred", 42); } catch (myException $m) { echo $m; }
Vediamo infine un esempio di implementazione in cui definisco tre sottoclassi diverse di Exception
, all’interno di un blocco try
andrò a generare eccezioni diverse in base all’errore. E’ più semplice intuire il funzionamento leggendo il codice che a parole.
Poniamo che le tre classi che estendono Exception
(di cui non sto a scrivere il codice) siano miaException1
, miaException2
e miaException2
:
try { if ($a = 1) throw new miaException1(); if ($a = 2) throw new miaException2() if ($a = 2) throw new miaException3() echo "nessun errore"; } catch (miaException1() $e1) { echo " Sto gestendo l'eccezione 1. "; } catch (Exception $e) { echo " Sto gestendo l'eccezione 2 oppure l'eccezione 3. "; }
Da notare infine che ho creato due (invece che tre) cath
diversi che vengono eseguiti in base all’oggetto passato.
Se è di tipo miaException1
allora sarà eseguito il primo, mentre negli altri casi il secondo, visto che tutte le classi ereditano da Exception
.
2 risposte su “PHP – Gestione delle Eccezioni”
Ciao, c’è una cosa che non ho capito di questo argomento e che nessun blog/sito spiega.
In un contesto di programmazione OOP, il blocco try/catch va posto nel metodo o nell’implementazione dello stesso?
Grazie mille!
No so se ho capito bene la domanda ma direi che la soluzione più logica è lanciare l’eccezione nella dichiarazione del metodo e quindi il try/catch al di fuori, ovvero nel client che chiama il metodo.
Quindi in un’ipotetica applicazione MVC eccezione nel modello e try/catch sul controller.