back to top

PHP try e catch – Gestione delle eccezioni in PHP

Nello scripting server side in PHP, gli errori possono gestiti tramite eccezioni. Questo approccio, che i programmatori in Java o C++ conosceranno già molto bene, consente di separare nettamente, già in fase di sviluppo, la gestione degli errori dalla logica dell’applicativo.

Dato che nella programmazione, gli errori sono inevitabili, diviene necessario creare degli accorgimenti che limitino il più possibile le perdite di tempo legate alla ricerca dei frammenti di codice errati velocizzando, contestualmente, la loro risoluzione.

Fino alla versione 4 di PHP, purtroppo, non c’era molto da fare: si scriveva il codice e poi lo si testava, gli errori "venivano fuori" e si andava alla ricerca della riga affetta dall’errore per poi applicare la soluzione adeguata.

Exception Handling in PHP

Con PHP 5, per fortuna, sono stati introdotti alcuni nuovi strumenti per l’analisi del nostro codice e per la razionalizzazione dei tempi di intervento a carico delle istruzioni mal digitate.

La logica che stà alla base dell’Exception Handling in PHP prende il nome di try (prova), throw (lancia) e catch (cattura), per cui il controllo delle eccezioni emula in parte l’azione svolta dalle istruzioni di controllo o condizionali come if ed else.

Se per esempio salviamo il seguente codice in una pagina chiamata eccezione.php, e lo lanciamo:

<?
throw new Exception('Errore!!!!!!!!');
?>

prevedibilmente, il risultato ottenuto sarà simile all’output riportato qui di seguito:

Fatal error: Uncaught exception 'Exception' 
with message 'Errore!!!!!!!!' 
in c:\programmi\php\www\error.php:2 Stack trace: #0 {main} 
thrown in c:\programmi\php\www\error.php on line 2

Al lancio dello "scriptino" abbiamo due effetti: il primo è la notifica di un Uncaught exception (letteralmente: "eccezione non catturata"), il secondo, ben più importante ai fini dell’Exception Handling, è il fatto che a seguito di questa notifica il resto delle istruzioni contenute nel codice, se presenti, non verranno eseguite.

In pratica, in questo caso l’effetto di un’azione di throwning sul codice PHP può essere paragonato a quello di una clausola die() che blocca l’esecuzione del listato a seguito di un controllo.

Try, throw e catch delle eccezioni in PHP

L’azione di controllo svolta dalla logica del try, throw e catch prevede quindi due esiti possibili:

  • o l’eccezione viene rilevata (catching con esito positivo) e quindi le istruzioni previste nel listato successivo all’errore non vengono escluse dal ciclo di esecuzione stabilito dal sorgente;
  • oppure, l’eccezione non viene rilevata (Uncaught exception) e quindi i possibili input previsti vengono abortiti e non producono effetti (o, per meglio dire, non vengono prodotti come effetto).

Per eseguire efficacemente il catching di un’eccezzione è possibile racchiudere il codice destinato all’esecuzione all’interno di un blocco in cui è prevista la prova e il lancio del listato (un cosiddetto blocco try and catch). All’interno di questo blocco di istruzioni potremo operare una distinzione efficace tra codice privo di errori e codice in grado di produrre notifiche di errore.

Allo scopo di chiarire meglio quanto appena espresso, un esempio pratico può essere di grande aiuto:

<?
try {    
  print "Stampa questo codice.";   
  throw new Exception('<br />Contollo delle eccezioni.');
  print "Blocca tutto!!";
} 
catch(Exception $var) {
  print $var->getMessage();
}
?>

Salviamo il codice appena proposto in una pagina chiamata, ad esempio, eccezione2.php ed eseguiamola. Così facendo riceveremo in output la stampa a video delle seguenti stringhe:

Stampa questo codice.
Contollo delle eccezioni.

Cosa è accaduto? apparentemente non molto, ma in relatà il nostro listato ha eseguito tutta una serie di operazioni che, naturalmente, evidenziano nell’output solo il loro risultato finale.

Innazitutto la prima stringa destinata alla stampa a video ("Stampa questo codice.") non viene sottoposta a controlli nè produce eccezioni, ma rientra comunque nel blocco di try; l’istruzione ad essa correlata verrà eseguita correttamente.

In secondo luogo viene lanciata un’eccezione seguendo la stessa procedura utilizzata nell’esempio precedente. L’eccezione non è stata ancora sottoposta ad un’azione di catching e quindi l’istruzione immediatamente sottostante, la stampa a video della stringa "Blocca tutto!!" non viene eseguita.

Viene effettuato il catching dell’eccezione e l’effetto conseguente al lancio di quest’ultima viene passato come valore ad una variabile ($var).

Infine, il metodo getMessage() raccoglie la variabile prodotta dall’azione di catching accettandola come parametro e viene stampata a video la stringa che le è stata assegnata come valore.

Try e catch con notifica dell’eccezione

Nel precedente paragrafo abbiamo descritto un primo esempio riguardante la possibilità di creare un try and catch block all’interno del quale testare gli output derivanti dal sistema di controllo denominato try, throw e catch.

L’esempio precedente non prevede di visualizzare le notifiche di errore al presentarsi di un’eccezione, quindi ora presenteremo del codice destinato ad una funzione esattamente contraria. Salviamo il listato esposto qui sotto in un file chiamato, ad esempio, eccezione3.php:

<?
try {
  $n1 = -1000;
  $n2 = -2; 
  if ( $n1 < $b2 )
  {
    throw new Exception($n1 . " è inferiore a " . $n2 . "<br />");
    echo "Prova a stamparmi se ci riesci!";
  }
}
catch (Exception $excp) {
  echo "Alt!! Ho trovato un'eccezione:<br />", $excp;
}
?>

Di seguito, riportiamo per completezza espositiva la stampa a video dell’output conseguente al test del codice appena digitato:

Alt!! Ho trovato un'eccezione:
exception 'Exception' with message '-1000 è inferiore a -2
' in c:\programmi\php\www\err.php:7 Stack trace: #0 {main}

Lo script proposto ci riporta a quanto detto all’inizio di questo articolo circa quanto accadeva sino a PHP 4: il limite insito in un sistema come quello stava nell’impossibilità di poter "specializzare" le operazioni di Exception Handling predefinendo la tipologia di reazione a seconda delle differenti possibilità di errore.

Nel codice proposto nell’esempio qui sopra abbiamo innanzitutto sottoposto delle istruzioni a try; di seguito abbiamo lanciato, all’interno del blocco try, un’eccezione tramite throw e questo ha determinato l’impossibilità di eseguire le ulteriori istruzioni poste all’interno dello stesso blocco try.

L’eccezione è stata quindi istanziata quale oggetto appartenente alla classe precedentemente definita, cioè Exception. L’istanza, conferendo delle proprietà all’oggetto lo ha reso riutilizzabile, infatti, lo ritroviamo al di fuori del blocco di try dove diviene argomento di un’istruzione e non ne blocca l’esecuzione.

Variabili e metodi per le eccezioni in PHP

In questo articolo descriveremo le variabili e i metodi che entrano in gioco nelle azioni di Exception Handling, entrambi sono elementi costitutivi è nativi della classe Exception, vera protagonista della gestione degli errori tramite eccezioni.

La variabili

Per quanto riguarda le variabili, vanno presi in considerazione essenzialmente tre voci:

  • Exception :: message: il messaggio di errore che verrà passato come argomento al costruttore della classe.
  • Exception :: line: il punto esatto del blocco di codice in cui viene generato l’errore.
  • Exception :: file:il nome del file PHP in cui a origine l’errore gestito tramite eccezione.

Le tre variabili appena descritte sono "protette", non potranno quindi essere riscritte e ogni tentativo di modifica a loro carico non farà altro che generare la notifica di un errore.

I metodi

Passiamo ora ai metodi. Questi ultimi sono pubblici e quindi accessibili in tutto il contesto appartenente alla classe in cui viene istanziato l’oggetto. Per la precisione possiamo distinguere 5 diversi metodi:

  • Exception :: getMessage(): lo abbiamo descritto in precedenza; esso è destinato a raccogliere come parametro la notifica di errore che viene generata dal controllo delle eccezioni. In pratica reinvia il messagio di errore come parametro al costruttore della classe di riferimento.
  • Exception :: getLine(): è il metodo che permette il reinvio alla riga di codice in cui si verifica l’errore.
  • Exception :: getTrace(): metodo che reinvia ad una tabella associtiva riguardante le caratteristiche dell’errore.
  • Exception :: getTraceAsString(): metodo che svolge una funzione similare all’Exception :: getTrace() ma crea una stringa con lo stesso contenuto di informazioni.

Il metodo Exception :: getTrace()

Exception :: getTrace() si presenta come il metodo più complesso in quanto contiene differenti tipi di informazioni riguardanti l’entità dell’errore gestito. All’interno di quest’ultimo metodo rileviamo 6 differenti elementi costitutivi che potremo riassumere nell’elenco seguente:

  • file: il documento in cui si verifica l’errore.
  • line: la riga di codice in cui si verifica l’errore.
  • function: la funzione coinvolta nell’errore.
  • class: la classe coinvolta nell’errore.
  • type: il modo in cui viene richiamato il metodo che potrebbe essere statico o dinamico.
  • args: gli argomenti passati al metodo raccolti in una tabella associativa.

Una classe per la gestione delle eccezioni

Dopo la nostra breve discussione sulle dinamiche e le procedure da adottare per la gestione degli errori tramite eccezioni in PHP 5, cercheremo di chiarire definitivamente le idee al lettore presentandogli un esempio pratico riguardante l’utilizzo del sistema try, throw e catch.

Nello specifico creeremo una classe da poter impiegare in un’operazione abbastanza frequente nello sviluppo di applicazioni in PHP: una funzione per l’apertura di un file in lettura.

Chiameremo la nostra funzione personalizzata ApriScatole(), mentre la classe di appartenenza prenderà il nome di provaEccezione. Di seguito riportiamo il listato completo di funzione e utilizzo pratico della stessa:

<?
//definizione della classe
class provaEccezione {

  //creiamo la funzione 
  public function ApriScatole($file) {
    if(!@fopen($file, 'r')) 
    {
      //stabiliamo le modalità di gestione dell'errore
      throw new Exception ('Il ' . $file . 'non si apre!!!');
    }
  }
}

//istanza
$obj = new provaEccezione;

//tentiamo di aprire un file inesistente
try {
  $obj -> ApriScatole('/percorso/file_inesistente.txt');
  //se il file esiste stampo a video una conferma
  echo 'Ho aperto il file!';
} 

//cathing dell'eccezione
catch (Exception $excp) {
  echo $excp -> getMessage();
}
?>

Basterà il semplice test dello script appena presentato per osservare gli effetti della gestione dell’errore.

In pratica non abbiamo fatto altro che definire una classe all’interno della quale è stata creata una funzione che controlla l’effettiva apertura in lettura di un file. Se il file passato come argomento non viene aperto, allora l’errore viene gestito secondo le modalità previste nella fase di throw.

Per testare la funzione abbiamo proceduto con l’istanza di un oggetto nel tentativo di aprire un file inesistente utilizzando la funzione appena creata, ma l’operazione porterà logicamente ad un errore la cui notifica verrà raccolta tramite catch e visualizzata tramite il metodo getMessage().

Altri contenuti interessanti

Pubblicità
Claudio Garau
Claudio Garau
Web developer, programmatore, Database Administrator, Linux Admin, docente e copywriter specializzato in contenuti sulle tecnologie orientate a Web, mobile, Cybersecurity e Digital Marketing per sviluppatori, PA e imprese.

Leggi anche...

Cannot modify header information – headers already sent: come risolvere l’errore PHP

L'errore di PHP cannot modify header information - headers...

Ricavare l’estensione di un file con PHP

Quando si lavora con i file in un'applicazione web,...

GD Library: creazione, manipolazione e ridimensionamento immagini con PHP

Le librerie GD (o GD Library), sono componenti fondamentali...

PHP: impostare il fuso orario italiano

Le tue pagine PHP non mostrano l’orario corretto? Probabilmente...

5 script PHP per gestire BBCode

A volte può aversi l'esigenza di dover offrire agli...
Pubblicità