Il logo del sito

Appunti su PHP

Traduzione da PHP Exception Handling

PHP Exception Handling

§ 1. PHP Exception Handling

Le eccezioni sono usate per modificare il normale flusso di uno script quando si verifica un errore.

§ 1.1 Che cosa è una eccezione

Con PHP arriva un nuovo modo object-oriented di trattare gli errori.

La gestione delle eccezioni è usata per modificare il normale flusso di esecuzione del codice al verificarsi di una specifica condizione di errore. Questa condizione è chiamata eccezione.

Ecco quello che normalmente succede quando si innesca una eccezione:

Mostreremo diversi metodi di gestione delle eccezioni:

Nota: Le eccezioni devono essere usate esclusivamente per la gestione delle condizioni di errore, e non per far saltare a piacere il flusso di esecuzione.

§ 1.2 Uso base

Quando una eccezione viene lanciata, il codice successivo al punto in cui l'eccezione è lanciata non sarà più eseguito, e PHP proverà a trovare il corrispondente blocco di cattura per quella specifica eccezione.

Se una eccezione non viene catturata, verrà generato un errore fatale con un messaggio di "Uncaught Exception".

Proviamo a lanciare una eccezione senza catturarla:


<?php
//create function with an exception
   function checkNum($number) {
      if($number>1) {
         throw new Exception("Value must be 1 or below");
      }
   return true;
}

//trigger exception
   checkNum(2);
?>

Lo script precedente provocherà un errore come questo:

Fatal error: Uncaught exception 'Exception'

with message 'Value must be 1 or below" in c:\webfolder\test.php:6

Stack trace: #0 c:\webfolder\test.php(12):

checkNum(28)#1 {main} thrown in c:\webfolder\test.php on line 6

§ 1.2.1 Try, throw and catch

Per evitare gli errori dell'esempio precedente, abbiamo bisogno dell'appropriato codice per gestire una eccezione. Questo dovrebbe includere:

  1. Try - una funzione che usa un eccezione dovrebbe essere in un blocco try. Se l'eccezione non viene innescata il codice continuerà normalmente. Se una eccezione viene innescata essa viene "lanciata";
  2. Throw - è come inneschi l'eccezione. Ogni "throw" deve avere almeno un "catch";
  3. Catch - un blocco "catch" cattura l'eccezione e crea un oggetto contenente le informazioni sull'eccezione.

Inneschiamo una eccezione in modo corretto:


<?php
//create function with an exception
   function checkNum($number) {
      if($number>1) {
         throw new Exception("Value must be 1 or below");
      }
      return true;
   }

//trigger exception in a "try" block
   try {
      checkNum(2);
  //If the exception is thrown, this text will not be shown
      echo 'If you see this, the number is 1 or below';
   }

//catch exception
   catch(Exception $e) {
      echo 'Message: ' .$e->getMessage();
   }
?>
Message: Value must be 1 or below

Lo script precedente provocherà un errore come questo:

Message: Value must be 1 or below

Spiegazione dell'esempio

Lo scrip appena illustrato lancia e cattura una eccezione:

  1. La funzione checkNum() controlla se un numero è più grande di 1. Se così lancia un eccezione;
  2. La funzione checkNum() è chiamata in un blocco try;
  3. L'eccezione all'interno della funzione checkNum() viene lanciata;
  4. Il blocco catch cattura l'eccezione e crea l'oggetto $e contenente le informazioni sulla eccezione.
  5. Il messaggio di errore viene visualizzato con il metodo $e->gettMessage() dell'oggetto eccezione.

Esiste un metodo per aggirare la regola, "ogni eccezione deve avere un catch". E' quello di creare un top level exception handler. Lo vedremo nel prossimo paragrafo.

§ 1.3 Creare una classe personalizzata per la gestione delle eccezioni

Occorre estendere la classe exception:


<?php
   class customException1 extends Exception {
      public function errorMessage() {
    //error message
         $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
            .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
         return $errorMsg;
      }
   }

   $email = "someone@example...com";

   try {
  //check if
      if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
    //throw exception if email is not valid
         throw new customException1($email);
      }
   }

   catch (customException1 $e) {
      //display custom message
      echo $e->errorMessage();
   }
?>
Error on line 219 in /var/www/virtual/clamin.it/htdocs/TestPages/php_Exception.php: someone@example...com is not a valid E-Mail address

La nuova classe è una copia della vecchia classe exception con in più la funzione errorMessage(). Eredita le proprietà ed i metodi della vecchia classe così che possiamo usare metodi come getLine(), getFile() e getMessage().

Spiegazione dell'esempio

Lo scrip appena illustrato lancia e cattura una eccezione con una classe exception personalizzata:

  1. La customException1 estende la class Exception ereditandone metodi e proprietà;
  2. La funzione errorMessage() restituisce un messaggio di errore se un indirizzo email non è valido;
  3. La variabile $email viene settata con un indirizzo email non valido;
  4. Il blocco try viene eseguito e lancia una eccezione dal momento che l'indirizzo email non è valido
  5. Il blocco catch cattura l'errore ed emette il messaggio di errore.

§ 1.4 Eccezioni multiple


<?php
   class customException2 extends Exception {
      public function errorMessage() {
    //error message
         $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
            .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
         return $errorMsg;
      }
   }

$email = "someone@example.com";

   try {
  //check if
      if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
    //throw exception if email is not valid
         throw new customException2($email);
      }
  //check for "example" in mail address
      if(strpos($email, "example") !== FALSE) {
         throw new Exception("$email is an example e-mail");
      }
   }

   catch (customException2 $e) {
      echo $e->errorMessage();
   }

   catch(Exception $e) {
      echo $e->getMessage();
   }
?>
someone@example.com is an example e-mail

Spiegazione dell'esempio

Lo scrip appena illustrato lancia e cattura una eccezione con una classe exception personalizzata:

  1. La customException2 estende la class Exception ereditandone metodi e proprietà;
  2. La funzione errorMessage() restituisce un messaggio di errore se un indirizzo email non è valido;
  3. La variabile $email viene settata con un indirizzo email valido ma che contiene la stringa "example" ;
  4. Il blocco try viene eseguito e non lancia una eccezione sulla prima condizione.
  5. La seconda condizione testata nel blocco try lancia una eccezione sulla stringa "example"
  6. Il blocco catch cattura l'errore ed emette il messaggio di errore.

§ 1.5 Rilancio di eccezioni

A volte, quando una eccezione viene catturata, può essere necessario lanciare una nuova eccezione dal blocco catch.


<?php
   class customException extends Exception {
      public function errorMessage() {
    //error message
         $errorMsg = $this->getMessage().' is not a valid E-Mail address.';
         return $errorMsg;
      }
   }

   $email = "someone@example.com";

   try {
      try {
    //check for "example" in mail address
         if(strpos($email, "example") !== FALSE) {
      //throw exception if email is not valid
            throw new Exception($email);
         }
      }
      catch(Exception $e) {
    //re-throw exception
         throw new customException($email);
      }
   }

   catch (customException $e) {
  //display custom message
      echo $e->errorMessage();
   }
?>
someone@example.com is not a valid E-Mail address.

Spiegazione dell'esempio

Questa struttura mi è decisamente nuova:

  1. La customException estende la class Exception ereditandone metodi e proprietà;
  2. La funzione errorMessage() restituisce un messaggio di errore se un indirizzo email non è valido;
  3. La variabile $email viene settata con un indirizzo email valido ma che contiene la stringa "example" ;
  4. Il blocco try contiene un altro blocco try per rendere possibile il rilancio di una eccezione..
  5. Il blocco try lancia una eccezione sulla stringa "example".
  6. Il blocco catch cattura l'eccezione e rilancia una customException.
  7. La customException viene catturata ed emette il messaggio di errore.

§ 1.6 Impostare una top level exception handler

La funzione set_exception_handler() setta una funzione utente per gestire tutte le eccezioni non catturate.


<?php
   function myException($exception) {
      echo "<b>Exception:</b> " . $exception->getMessage();
   }

   set_exception_handler('myException');

   throw new Exception('Uncaught Exception occurred');
?>

Lo script precedente emetterà un output come questo:

Exception: Uncaught Exception occurred

§ 1.7 Regole per le eccezioni