La gestione delle eccezioni consente non soltanto di ricevere notifiche dall'esecuzione di un'applicazione nel caso in cui vengano generati comportamenti non previsti (come per esempio i malfunzionamenti), ma anche di raccogliere dettagli relativi alla tipologia di errore verificatosi; per massimizzare l'utilità delle eccezioni, è sufficiente osservare alcune semplici regole che consentono di impiegare questo strumento in modo più proficuo permettendo agli script di inviare notifiche contenenti informazioni precise da utilizzare nelle fasi di sviluppo, produzione ed eventualmente di correzione.
Semplici esempi di gestione delle eccezioni
Come è noto, PHP integra nativamente un sistema abbastanza completo per la gestione delle eccezioni con particolare attenzione verso gli errori prodotti dall'esecuzione degli script, se nel codice digitato manca un ;
(punto e virgola) per la chiusura di un'istruzione o una variabile viene considerata una costante non definita perché manca del simbolo $
(simbolo del dollaro), PHP è in grado di segnalare il problema e di indicare all'utilizzatore la riga coinvolta.
Ma le eccezioni non sono necessariamente degli "errori" nel codice, più semplicemente possono anche essere dei comportamenti non voluti o degli esiti non previsti in seguito ad una richiesta da parte di un client. Se per esempio un utilizzatore richiede di accedere ad un determinato file e questo non è più disponibile sul server non è possibile dire che questo sia il risultato di un errore in sede di sviluppo, soprattutto se l'applicazione è stata dotata di accorgimenti in grado di gestire questo tipo di eccezione.
Le eccezioni possono quindi essere anche uno strumento valido per inviare informazioni importanti all'utenza e in generale a chi non ha la possibilità di accedere direttamente al codice sorgente degli script. Un modo molto semplice di gestire le eccezioni all'interno di un'applicazione è quello di utilizzare le istruzioni condizionali, un comune blocco IF - ELSE
consente di ricavare alcune informazioni riguardo agli esiti delle esecuzioni.
Il listato contenuto nello script seguente rappresenta un esempio di elementare gestione delle eccezioni:
<?php # definizione della funzione function dividi($n) { # blocco condizionale if (!$n) { throw new Exception("Division by zero."); } # valore di ritorno della funzione else return 10/$n; } # esecuzione della funzione try { echo dividi(10); echo "<br/>n"; echo dividi(0); echo "<br/>n"; # gestione dell'eccezione } catch (Exception $e) { echo "Rilevata eccezione: ". $e->getMessage(); } # codice al di fuori della gestione delle eccezioni echo "<br/>n"; echo "Html.it"; ?>
Il codice proposto determina una serie di semplici comportamenti:
- Introduce una funzione che ha il compito di controllare che una determinata variabile sia stata valorizzata o abbia un valore diverso da "0" (cioè non sia FALSE), soltanto nel caso in cui questa variabile rispetti le condizioni proposte verrà utilizzata come divisore dell'operazione prevista.
- Propone due diverse esecuzioni della funzione: la prima prevede il passaggio di un valore utilizzabile come divisore, da infatti luogo al comportamento previsto dal valore di ritorno; la seconda prevede il passaggio di un "non valore", l'applicazione dovrebbe produrre un errore ma ciò non avviene in quanto l'eccezione è stata prevista nel codice della funzione.
- Produce la notifica dell'eccezione prevista e rilevata.
- Esegue il resto del codice e produce gli output previsti nonostante sia stata rilevata un'eccezione.
Eseguendo lo script vengono prodotti i seguenti output:
- "1" : il risultato dell'azione della funzione nel caso del passaggio di un valore utilizzabile;
- "Rilevata eccezione: Division by zero.": risultato della gestione dell'eccezione;
- "Html.it": output delle istruzioni per le quali non è stata applicata la gestione delle eccezioni.
La funzione potrà essere utilizzata, per esempio, per valutare valori inviati arbitrariamente dagli utenti tramite metodo (POST
, GET
, SESSION
etc.), in questo modo sarà possibile gestire facilmente i casi in cui vengano passati all'applicazione variabili a cui corrispondono valori non validi.
Nello stesso modo sarà possibile utilizzare la gestione delle eccezioni per notificare l'assenza di una determinata risorsa all'interno di un percorso specificato, come accade per l'esempio successivo:
<?php # esecuzione dell'applicazione try { # definizione della condizione if(!@include("/percorso/immagini/image.jpeg")) { # istanza dell'eventuale eccezione throw new Exception("Impossibile accedere al file richiesto."); } } # notifica dell'eccezione catch(Exception $e) { echo $e->getMessage(); } ?>
Come è noto, per la gestione delle eccezioni PHP 5 ha importato un metodo utilizzato nei linguaggi di programmazione basato sul costrutto try (prova), throw (lancia) e catch (intercetta); grazie a questo costrutto una determinata eccezione potrà essere lanciata e intercettata all'interno del codice PHP, questo codice potrà essere incluso all'interno di un blocco try a cui corrisponderà almeno un blocco catch che permetterà di generare il comportamento previsto per l'eccezione (generalmente ma non necessariamente una notifica).
Exception: proprietà e metodi
Si analizzi un ulteriore caso di gestione delle eccezioni, questa volta l'esempio è incentrato sul codice necessario per la connessione di uno script al DBMS MySQL:
<?php # inserimento del codice da eseguire nel blocco try try { $connessione = @mysql_connect("localhost", "username", "password"); # codizione if ($connessione === false) { # istanza dell'eccezione throw new Exception("Impossibile connettersi al DBMS."); } echo "Connessione al DBMS effettuata."; @mysql_close($connessione); } # intercettazione dell'eccezione e notifica catch (Exception $e) { die("Attenzione: " . $e->getMessage() . "<br/>n"); } ?>
La logica che presiede al funzionamento della piccola applicazione presentata è molto semplice: nel caso in cui i dati forniti per la connessione non dovessero essere validi verrà mostrata la notifica prevista per la gestione dell'eccezione.
In tutti gli esempi mostrati in questa breve trattazione abbiamo utilizzato l'istruzione "throw new" per effettuare la chiamata a Exception; nel blocco catch è stato invece utilizzato un puntatore all'oggetto (in questo caso $e) che è istanza della classe Exception.
Nel momento in cui l'eccezione viene intercettata, l'applicazione è in grado di accedere tramite il puntatore ai metodi disponibile grazie alla classe; i metodi disponibili per l'oggetto sono sei:
- getCode(): consente di individuare il codice per il quale è stata impostata l'eventuale eccezione.
- getFile(): è un metodo riferito al file in cui si è verificata l'eccezione.
- getLine(): permette di individuare la riga di codice in cui si è dato luogo all'eccezione.
- getMessage(): restituisce il messaggio che è stato definito per notificare l'eventuale eccezione.
- getTrace(): restituisce sotto forma di array numerosi dettagli riguardanti un errore tra cui anche il nome del file e la riga in cui si verifica l'errore.
- getTraceAsString(): è simile al metodo precedente ma restituisce i dettagli sotto forma di stringa.
La funzione set_exception_handler
Un metodo alternativo per gestire le eccezioni in modo efficace può essere quello di utilizzare la funzione set_exception_handler()
che permette all'utente di definire e impostare una propria funzione di gestione delle eccezioni. Si tratta di una soluzione molto utile nel caso in cui un'eccezione non può essere individuata all'interno di un blocco try - catch; l'esecuzione verrà poi conclusa in seguito alla chiamata di una funzione denominata per convenzione exception_handler()
.
exception_handler()
dovrà però essere definita prima della chiamata alla funzione set_exception_handler()
a cui dovrà essere passata l'eccezione individuata come unico argomento; l'esito dell'applicazione di set_exception_handler()
può essere la restituzione della funzione di gestione delle eccezioni definita dall'utente o FALSE in presenza di un errore.
Un semplice esempio di utilizzo della funzione set_exception_handler()
può essere il seguente:
<?php # definizione della funzione di terminazione function exception_handler($e) { echo "Eccezione non intercettata: " , $e->getMessage(), "n"; } # definizione della funzione per la gestione delle eccezioni set_exception_handler("exception_handler"); # istanza dell'eccezione throw new Exception("Eccezione non intercettata"); echo "Esecuzione non consentita.n"; ?>
Per ripristina una funzione per la gestione delle eccezioni definita in precedenza sarà necessario utilizzare la funzione denominata "restore_exception_handler()", essa può essere introdotta dopo aver modificato la funzione di gestione delle eccezioni (nativa o definita dall'utilizzatore) attraverso l'istruzione set_exception_handler().
Conclusioni
PHP 5 mette a disposizione degli sviluppatori uno strumento avanzato per la gestione delle eccezioni, utilizzarle in modo adeguato permette di dettare alle applicazioni dei comportamenti da generare nel caso di malfunzionamenti (comprese le segnalazioni per gli utenti) e di recuperare informazioni utili per gestire gli errori in modo più preciso e rapido.