SlideShare a Scribd company logo
Error Handling
Introduction How to write an error handler. Normally, it displays a message indicating the cause of the error and may also terminate script execution when a PHP script encounters an error.  Now, while this behaviour is acceptable during the development phase, it cannot continue once a PHP application has been released to actual users. In "live" situations, it is unprofessional to display cryptic error messages (which are usually incomprehensible to non-technical users). It is more professional to intercept these errors and either resolve them (if resolution is possible), or notify the user with an easily-understood error message (if not).
There are 3 basic types of runtime errors in PHP:  Notices : These are trivial, non-critical errors that PHP encounters while executing a script. By default, such errors are not displayed to the user at all – we can change this default behaviour.  Warnings : These are more serious errors - for example, attempting to include() a file which does not exist. By default, these errors are displayed to the user, but they do not result in script termination.  Fatal errors : These are critical errors - for example, instantiating an object of a non-existent class, or calling a non-existent function. These errors cause the immediate termination of the script, and PHP's default behaviour is to display them to the user when they take place.
It should be noted that a syntax error in a PHP script – (EG: missing brace or semi-colon) is treated as a fatal error and results in script termination (stop execution).  PHP errors can be generated by: Zend engine PHP built-in functions user-defined functions  They may occur at startup, at parse-time, at compile-time or at run-time.  During the debug phase: Use E_ALL type to see all fatal and non-fatal errors generated by our script. Use the new E_STRICT error type to view errors that affect the forward compatibility of our code in PHP 5.
Early Warning Example 1 we get a non-fatal error (E_WARNING) it still get executed but with non-fatal error Example 2 it call non-existent function generate a fatal error immediately stops script execution
Example 1 < ?php // initialize the $string variable $string =  'a string'; // explode() a string // this will generate a warning or E_WARNING because the number of arguments to explode() is incorrect explode ($string); ? >   Output Warning : Wrong parameter count for explode() in  C:ampwwest2art12g1.php  on line  8
Example 2 < ?php // call a non-existent function // this will generate a fatal error   (E_ERROR) callMeJoe () ; ? >  Output Fatal error : Call to undefined function callMeJoe() in  C:ampwwest2art12g2.php  on line  5
Example 3 control which errors are displayed to the user (built-in PHP function called error_reporting()) this function tells the script to report only errors that match that type &quot;hide&quot; non-fatal errors Example 4 Use a similar technique to turn off the display of fatal errors
Example 3 < ?php // report only fatal errors error_reporting (E_ERROR); // initialize the $string variable $string =  'string'; // attempt to explode() a string // this will not generate a warning because only fatal errors are reported explode ($string); ? >   Output No output
Example 4 < ?php // report no fatal errors error_reporting (~E_ERROR); // call a non-existent function callMeJoe(); ? >   Output No output
Although the script above will not display a visible error message, script execution will still stop at the point of error and statements subsequent to that point will not be executed. error_reporting() gives you control over which errors are displayed; it doesn't prevent the errors themselves.
Rolling Your Own   Changing the way errors are handled.  Function called set_error_handler(), it allows to divert all PHP errors to a custom function that are defined, instead of sending them to the default handler. This custom function must be capable of accepting a minimum of two mandatory arguments: error type corresponding descriptive message and up to three additional arguments the file name  line number where the error occurred dump of the variable space at the time of error
Example 5 The set_error_handler() function tells the script that all errors are to be routed to my user-defined oops() function This function is set up to accept five arguments:- error type message file name line number context  These arguments are then used to create an error page that is friendlier and more informative than PHP's standard one-line error message
Example 5 < ?php // define a custom error handler set_error_handler ( 'oops' ); // initialize the $string variable $string =  'a string' ; // explode() a string // this will generate a warning because the number of arguments to explode() is incorrect // the error will be caught by the custom error handler explode ($string);
// custom error handler function   oops($type, $msg, $file, $line, $context)  { echo   &quot;<h1>Error!</h1>&quot;; echo   &quot;An error occurred while executing this script. Please contact the <a href=mailto:webmaster@somedomain.com>webmaster</a> to report this error.&quot;; echo   &quot;<p />&quot;; echo   &quot;Here is the information provided by the script:&quot;; echo   &quot;<hr><pre>&quot;; echo   &quot;Error code: $type<br />&quot;; echo   &quot;Error message: $msg<br />&quot;; echo   &quot;Script name and line number of error: $file:$line<br />&quot;; $variable_state  = array_pop ($context); echo  &quot;Variable state when error occurred: &quot;; print_r ($variable_state); echo   &quot;</pre><hr>&quot;; } ?> Output Error!
An error occurred while executing this script. Please contact the  webmaster  to report this error.Here is the information provided by the script: Error code: 2 Error message: Wrong parameter count for explode() Script name and line number of error: C:ampwwest2art12g5.php:12 Variable state when error occurred: a string
Example 6 Can use this custom error handler to alter the error message the user sees, on the basis of the error type Note that certain error types can't be handled in this way.  For example, a fatal E_ERROR will prevent the PHP script from continuing. So, it can never reach a user-created error-handling mechanism.
Example 6 < ?php // define a custom error handler set_error_handler ( 'oops' ); // initialize $string variable $string =  'a string' ; // this will generate a warning explode ($string); // custom error handler function  oops($type, $msg, $file, $line, $context) { switch  ($type) { // notices case  E_NOTICE: // do nothing break;
// warnings case  E_WARNING: // report error print   &quot;Non-fatal error on line $line of $file: $msg   <br />“; break; // other default: print  &quot;Error of type $type on line $line of $file: $msg <br />&quot;; break; } } ?> Output Non-fatal error on line 10 of C:ampwwest2art12g6.php: Wrong parameter count for explode()
Pulling the Trigger PHP allows you to use its built-in error handling system to raise your own custom errors as well.  This is accomplished via a function named trigger_error(), which allows you to raise any of the three error types reserved for users: E_USER_NOTICE, E_USER_WARNING and E_USER_ERROR.  When these errors are triggered, PHP's built-in handler will automatically wake up to handle them.  Example(triggerror6.php):
Example(triggerror6.php): < ?php   // function to test a number  // generates E_USER_WARNING if number is a float  // generates E_USER_ERROR is number is negative  function  testNumber($num)  {  // float  // trigger a warning  if  ( is_float ($num))  {   trigger_error (&quot;Number $num is not an integer&quot;,  E_USER_WARNING);  }   // negative  // trigger a fatal error  if  ($num  <   0 )  {  trigger_error (&quot;Number $num is negative&quot;,  E_USER_ERROR);  }  }  // test the function with different values  testNumber ( 100 ) ;  testNumber ( 5.6 ) ;  testNumber ( -8 ) ;  ? >   ----output----- Warning : Number 5.6 is not an integer in  C:ampwwest2art12riggerror6.php  on line  10 Fatal error : Number -8 is negative in  C:ampwwest2art12riggerror6.php  on line  16
Pulling the Trigger (cont..) The next example rewrites the previous script to use a user-defined error handler to have a custom error handler to handle your custom errors. Example(triggererror7.php):
Example(triggererror7.php): < ?php   // function to test a number  // generates E_USER_WARNING if number is a float  // generates E_USER_ERROR is number is negative  function  testNumber ( $num ) {  // float   // trigger a warning  if  ( is_float( $num )) {   trigger_error ( &quot;Number $num is not an integer&quot;,  E_USER_WARNING);  }   // negative  // trigger a fatal error  if  ($num  <   0 )  {  trigger_error (&quot;Number $num is negative“ , E_USER_ERROR);  }  }  // custom error handler   function  myErrorHandler($type, $msg, $file, $line, $context)  {  switch  ($type)  {  // warnings   case  E_USER_WARNING:  // report error   print  &quot;Non-fatal error on line $line of $file: $msg <br />&quot; ;  break ;
// fatals   case  E_USER_ERROR:  // report error and die()   die ( &quot;Fatal error on line $line of $file: $msg <br />&quot; );  break ;  // notices   default :  // do nothing   break ;  }  }  // set the name of the custom handler   set_error_handler ( 'myErrorHandler' ) ;  // test the function with different values   testNumber( 100 );  testNumber( 5.6 );  testNumber( -8 );  ? > -----output----- Non-fatal error on line 10 of C:ampwwest2art12riggerror7.php: Number 5.6 is not an integer Fatal error on line 16 of C:ampwwest2art12riggerror7.php: Number -8 is negative
Catching up In the exception-based approach, program code is wrapped in a try() block, and exceptions generated by it are &quot;caught&quot; and resolved by a catch() block.  Multiple catch() blocks are possible, each one dealing with a different error type; this allows developers to trap different types of errors and execute appropriate exception-handling.  When PHP encounters code wrapped within a try-catch() block: It first attempts to execute the code within the try() block.  If this code is processed without any exceptions being generated, control transfers to the lines following the try-catch() block.  If an exception is generated while running the code within the try() block, PHP stops execution of the block at that point and begins checking each catch() block to see if there is a handler for the exception.  If a handler is found, the code within the appropriate catch() block is executed; if not, a fatal error is generated.
Catching up (cont..) The exceptions themselves are generated via PHP's throw statement.  The throw statement needs to be passed a descriptive message, and an optional error code.  When the exception is raised, this description and code will be made available to the exception handler. Example(tryncatcherror8.php):
< ?php   // PHP 5   error_reporting ( 0 );  // try this code   try   {   $file  =   'somefile.txt' ;  // open file   if  ( ! $fh =  fopen ($file,  'r' ))   {  throw new Exception( 'Could not open file!' );  }   // read file contents   if  ( ! $data =  fread ($fh,  filesize ($file )))   {  throw new Exception( 'Could not read file!' );  }   // close file   fclose ($fh);  // print file contents   echo  $data;  }  // catch errors if any   catch  (Exception $e)  {   print   'Something bad just happened...' ;  }   ?>   ----output---- Something bad just happened... Example (tryncatcherror8.php):
Catching up (cont..) If the file doesn't exist or is unreadable, the throw statement will generate an exception (basically, an instance of PHP's built-in Exception object) and pass it a message describing the error.  When such an exception is generated, control passes to the first catch() block.  If the catch() block can handle the exception type, the code within the catch() block is executed. If the first catch() block cannot handle the generated exception, control passes to the next one.
Example (tryncatcherror9.php) < ?php   // PHP 5   error_reporting (0);  // try this code  try   {       $file  =   'somefile.txt ';       // open file       if  ( ! $fh  =   fopen ($file,  'r’ )) {          throw  new  Exception( 'Could not open file!' , 12);      }       // read file contents        if  ( ! $data  =   fread ($fh,  filesize ($file))) {          throw new Exception('Could not read file!', 9);      }      // close file        fclose ($fh);       // print file contents       echo  $data;  }  // catch errors if any  catch  (Exception $e) {       print  '<h2>Exception</h2>‘ ;      print   'Error message: '  . $e  -> getMessage () .   '<br />‘  ;       print   'Error code: '  . $e  -> getCode () .   '<br />‘  ;       print   'File and line:  ' . $e  -> getFile ().   '('  . $e->getLine () .   ‘)<br />‘  ;       print   'Trace:   '  . $e  -> getTraceAsString () .   '<br />  ';  }  ? >  ----output---- Exception Error message: Could not open file! Error code: 12 File and line: C:ampwwest2art12ryncatcherror9.php(12) Trace: #0 {main}
Catching up (cont..) When you run this script, you'll see that the message generated by the exception handler contains:  the descriptive data sent by throw,  an error code (also sent by throw),  the file name and line number where the exception occurred, and a stack trace indicating the exception's progress through the class hierarchy, if there is one.  This data is generated by calling the Exception object's getMessage(), getCode(), getFile(), getLine() and getTraceAsString() methods respectively inside the catch() block.  .
Adding Some Class You can handle different exceptions in different ways, by sub-classing the generic Exception object and using more than one catch() block.  Example(classerror10.php): Note that because PHP will always use the first catch() block that matches the exception type and because the generic Exception class matches all exceptions, the catch() blocks  must be arranged  in the  order of most specific first .
Example (classerror10.php) < ?php // PHP 5 // sub-class the Exception class class  NegativeNumException  extends  Exception  {} //class OutOfRangeException extends Exception {} class  FloatException  extends  Exception  {} // function to test a number function testNumber($num)  { // float // trigger an exception if  (is_float($num )) { throw  new  FloatException($num); } // negative // trigger an exception if  ($num  <   0 )  { throw  new  NegativeNumException($num); } // out of range // trigger an exception if  ($num  >   1000  || $num  <  100 )  { throw  new  OutOfRangeException($num); } }
// try this code try   { testNumber (- 19 ) ; } // catch errors, if any catch   ( NegativeNumException $e ) { print   'A negative number was provided (' . $e -> getMessage (). '). Please provide a positive integer between 100 and 1000.<br />' ; } catch   ( OutOfRangeException $e ) { print   'The number provided is out of range (' . $e -> getMessage (). '). Please provide a positive integer between 100 and 1000.<br />' ; } catch  (FloatException $e)  { print   'The number provided is not an integer (' . $e -> getMessage (). '). Please provide a positive integer between 100 and 1000.<br />' ; } catch  (Exception $e)  { print   'Error message: '  . $e  -> getMessage () .   '<br />' ; print   'Error code: '  . $e  -> getCode () .   '<br />' ; print   'File and line: '  . $e  -> getFile () .   '('  . $e->getLine() .  ')<br />' ; print   'Trace: '  . $e  -> getTraceAsString () .   '<br />' ; } ?>   ----output---- A negative number was provided (-19). Please provide a positive integer between 100 and 1000.
Here's another example, this one illustrating a more useful application - using the exception model in a user authentication class to provide easy-to-understand error handling Example(classerror11.php) Here, depending on the type of error, either a FileException() or an AuthException() will be generated - and handled by the corresponding catch() block
Example (classerror11.php) < ?php   // PHP 5  // class definition  class  userAuth  {  // define properties  private  $username;  private  $passwd;  private  $passwdFile;  // constructor   // must be passed username and non-encrypted password   public  f unction  __construct($username, $password)  {  $this-> username  =  $username;  $this-> passwd  =  $password;  }  // set .htaccess-style file to check for passwords   public   function  setPasswdFile($file)  {  $this-> passwdFile = $file;  }  // perform password verification  public   function  authenticateUser()  {  // check that the file exists  if  ( !file_exists ( $this-> passwdFile))  {   throw  new  FileException( &quot;Password file cannot be found: &quot;  . $this-> passwdFile);  }
// check that the file is readable   if  ( !is_readable ( $this->passwdFile )) {  throw new FileException( &quot;Unable to read password file: &quot; .   $this-> passwdFile);  }  // read file  $data  = file ( $this-> passwdFile);  // iterate through file  foreach  ($data as $line) {  $arr  = explode ( &quot;:&quot; , $line);  // if username matches, test password  if  ($arr [ 0 ]   == $this-> username) {  // get salt and crypt(), assuming encryption  $salt  = substr ($arr[ 1 ],  0 ,  2 );  // if match, user/pass combination is correct   if  ($arr [ 1 ]   == crypt ( $this-> passwd, $salt)) {  echo   &quot;User was authenticated&quot; ;  // do some other stuff   }  // otherwise return exception  else  {  throw  new  AuthException( &quot;Incorrect password&quot; );  break ;  }  }  else  {  // could not find a username match  // return exception  throw  new  AuthException( &quot;No such user&quot; );  }  }  }  // end class definition   }
// subclass exceptions   class  FileException  extends  Exception  {} ;  class  AuthException  extends  Exception  {} ;  // try the code  try   {  // create instance  $ua  =  new userAuth ( &quot;joe&quot; ,  &quot;secret&quot; ) ;  // set password file  $ua -> setPasswdFile ( &quot;password.txt&quot; ) ;  // perform authentication  $ua -> authenticateUser () ;  }   // catch authentication failures, if any  catch   ( FileException $e ) {   // print file errors  print   &quot;A file error occurred. &quot; . $e -> getMessage () ;  }   catch   ( AuthException $e ) {  // an authentication error occurred   print   &quot;An authentication error occurred. &quot; . $e -> getMessage();  // more normally, redirect to new page on auth errors, e.g.   // header ('Location: login_fail.php');  }  catch  (Exception $e) {  print  &quot;An unknown error occurred&quot; ;  }  ? >   ----output--- A file error occurred. Password file cannot be found: password.txt

More Related Content

Php Error Handling

  • 2. Introduction How to write an error handler. Normally, it displays a message indicating the cause of the error and may also terminate script execution when a PHP script encounters an error. Now, while this behaviour is acceptable during the development phase, it cannot continue once a PHP application has been released to actual users. In &quot;live&quot; situations, it is unprofessional to display cryptic error messages (which are usually incomprehensible to non-technical users). It is more professional to intercept these errors and either resolve them (if resolution is possible), or notify the user with an easily-understood error message (if not).
  • 3. There are 3 basic types of runtime errors in PHP: Notices : These are trivial, non-critical errors that PHP encounters while executing a script. By default, such errors are not displayed to the user at all – we can change this default behaviour. Warnings : These are more serious errors - for example, attempting to include() a file which does not exist. By default, these errors are displayed to the user, but they do not result in script termination. Fatal errors : These are critical errors - for example, instantiating an object of a non-existent class, or calling a non-existent function. These errors cause the immediate termination of the script, and PHP's default behaviour is to display them to the user when they take place.
  • 4. It should be noted that a syntax error in a PHP script – (EG: missing brace or semi-colon) is treated as a fatal error and results in script termination (stop execution). PHP errors can be generated by: Zend engine PHP built-in functions user-defined functions They may occur at startup, at parse-time, at compile-time or at run-time. During the debug phase: Use E_ALL type to see all fatal and non-fatal errors generated by our script. Use the new E_STRICT error type to view errors that affect the forward compatibility of our code in PHP 5.
  • 5. Early Warning Example 1 we get a non-fatal error (E_WARNING) it still get executed but with non-fatal error Example 2 it call non-existent function generate a fatal error immediately stops script execution
  • 6. Example 1 < ?php // initialize the $string variable $string = 'a string'; // explode() a string // this will generate a warning or E_WARNING because the number of arguments to explode() is incorrect explode ($string); ? > Output Warning : Wrong parameter count for explode() in C:ampwwest2art12g1.php on line 8
  • 7. Example 2 < ?php // call a non-existent function // this will generate a fatal error (E_ERROR) callMeJoe () ; ? > Output Fatal error : Call to undefined function callMeJoe() in C:ampwwest2art12g2.php on line 5
  • 8. Example 3 control which errors are displayed to the user (built-in PHP function called error_reporting()) this function tells the script to report only errors that match that type &quot;hide&quot; non-fatal errors Example 4 Use a similar technique to turn off the display of fatal errors
  • 9. Example 3 < ?php // report only fatal errors error_reporting (E_ERROR); // initialize the $string variable $string = 'string'; // attempt to explode() a string // this will not generate a warning because only fatal errors are reported explode ($string); ? > Output No output
  • 10. Example 4 < ?php // report no fatal errors error_reporting (~E_ERROR); // call a non-existent function callMeJoe(); ? > Output No output
  • 11. Although the script above will not display a visible error message, script execution will still stop at the point of error and statements subsequent to that point will not be executed. error_reporting() gives you control over which errors are displayed; it doesn't prevent the errors themselves.
  • 12. Rolling Your Own Changing the way errors are handled. Function called set_error_handler(), it allows to divert all PHP errors to a custom function that are defined, instead of sending them to the default handler. This custom function must be capable of accepting a minimum of two mandatory arguments: error type corresponding descriptive message and up to three additional arguments the file name line number where the error occurred dump of the variable space at the time of error
  • 13. Example 5 The set_error_handler() function tells the script that all errors are to be routed to my user-defined oops() function This function is set up to accept five arguments:- error type message file name line number context These arguments are then used to create an error page that is friendlier and more informative than PHP's standard one-line error message
  • 14. Example 5 < ?php // define a custom error handler set_error_handler ( 'oops' ); // initialize the $string variable $string = 'a string' ; // explode() a string // this will generate a warning because the number of arguments to explode() is incorrect // the error will be caught by the custom error handler explode ($string);
  • 15. // custom error handler function oops($type, $msg, $file, $line, $context) { echo &quot;<h1>Error!</h1>&quot;; echo &quot;An error occurred while executing this script. Please contact the <a href=mailto:webmaster@somedomain.com>webmaster</a> to report this error.&quot;; echo &quot;<p />&quot;; echo &quot;Here is the information provided by the script:&quot;; echo &quot;<hr><pre>&quot;; echo &quot;Error code: $type<br />&quot;; echo &quot;Error message: $msg<br />&quot;; echo &quot;Script name and line number of error: $file:$line<br />&quot;; $variable_state = array_pop ($context); echo &quot;Variable state when error occurred: &quot;; print_r ($variable_state); echo &quot;</pre><hr>&quot;; } ?> Output Error!
  • 16. An error occurred while executing this script. Please contact the webmaster to report this error.Here is the information provided by the script: Error code: 2 Error message: Wrong parameter count for explode() Script name and line number of error: C:ampwwest2art12g5.php:12 Variable state when error occurred: a string
  • 17. Example 6 Can use this custom error handler to alter the error message the user sees, on the basis of the error type Note that certain error types can't be handled in this way. For example, a fatal E_ERROR will prevent the PHP script from continuing. So, it can never reach a user-created error-handling mechanism.
  • 18. Example 6 < ?php // define a custom error handler set_error_handler ( 'oops' ); // initialize $string variable $string = 'a string' ; // this will generate a warning explode ($string); // custom error handler function oops($type, $msg, $file, $line, $context) { switch ($type) { // notices case E_NOTICE: // do nothing break;
  • 19. // warnings case E_WARNING: // report error print &quot;Non-fatal error on line $line of $file: $msg <br />“; break; // other default: print &quot;Error of type $type on line $line of $file: $msg <br />&quot;; break; } } ?> Output Non-fatal error on line 10 of C:ampwwest2art12g6.php: Wrong parameter count for explode()
  • 20. Pulling the Trigger PHP allows you to use its built-in error handling system to raise your own custom errors as well. This is accomplished via a function named trigger_error(), which allows you to raise any of the three error types reserved for users: E_USER_NOTICE, E_USER_WARNING and E_USER_ERROR. When these errors are triggered, PHP's built-in handler will automatically wake up to handle them. Example(triggerror6.php):
  • 21. Example(triggerror6.php): < ?php // function to test a number // generates E_USER_WARNING if number is a float // generates E_USER_ERROR is number is negative function testNumber($num) { // float // trigger a warning if ( is_float ($num)) { trigger_error (&quot;Number $num is not an integer&quot;, E_USER_WARNING); } // negative // trigger a fatal error if ($num < 0 ) { trigger_error (&quot;Number $num is negative&quot;, E_USER_ERROR); } } // test the function with different values testNumber ( 100 ) ; testNumber ( 5.6 ) ; testNumber ( -8 ) ; ? > ----output----- Warning : Number 5.6 is not an integer in C:ampwwest2art12riggerror6.php on line 10 Fatal error : Number -8 is negative in C:ampwwest2art12riggerror6.php on line 16
  • 22. Pulling the Trigger (cont..) The next example rewrites the previous script to use a user-defined error handler to have a custom error handler to handle your custom errors. Example(triggererror7.php):
  • 23. Example(triggererror7.php): < ?php // function to test a number // generates E_USER_WARNING if number is a float // generates E_USER_ERROR is number is negative function testNumber ( $num ) { // float // trigger a warning if ( is_float( $num )) { trigger_error ( &quot;Number $num is not an integer&quot;, E_USER_WARNING); } // negative // trigger a fatal error if ($num < 0 ) { trigger_error (&quot;Number $num is negative“ , E_USER_ERROR); } } // custom error handler function myErrorHandler($type, $msg, $file, $line, $context) { switch ($type) { // warnings case E_USER_WARNING: // report error print &quot;Non-fatal error on line $line of $file: $msg <br />&quot; ; break ;
  • 24. // fatals case E_USER_ERROR: // report error and die() die ( &quot;Fatal error on line $line of $file: $msg <br />&quot; ); break ; // notices default : // do nothing break ; } } // set the name of the custom handler set_error_handler ( 'myErrorHandler' ) ; // test the function with different values testNumber( 100 ); testNumber( 5.6 ); testNumber( -8 ); ? > -----output----- Non-fatal error on line 10 of C:ampwwest2art12riggerror7.php: Number 5.6 is not an integer Fatal error on line 16 of C:ampwwest2art12riggerror7.php: Number -8 is negative
  • 25. Catching up In the exception-based approach, program code is wrapped in a try() block, and exceptions generated by it are &quot;caught&quot; and resolved by a catch() block. Multiple catch() blocks are possible, each one dealing with a different error type; this allows developers to trap different types of errors and execute appropriate exception-handling. When PHP encounters code wrapped within a try-catch() block: It first attempts to execute the code within the try() block. If this code is processed without any exceptions being generated, control transfers to the lines following the try-catch() block. If an exception is generated while running the code within the try() block, PHP stops execution of the block at that point and begins checking each catch() block to see if there is a handler for the exception. If a handler is found, the code within the appropriate catch() block is executed; if not, a fatal error is generated.
  • 26. Catching up (cont..) The exceptions themselves are generated via PHP's throw statement. The throw statement needs to be passed a descriptive message, and an optional error code. When the exception is raised, this description and code will be made available to the exception handler. Example(tryncatcherror8.php):
  • 27. < ?php // PHP 5 error_reporting ( 0 ); // try this code try { $file = 'somefile.txt' ; // open file if ( ! $fh = fopen ($file, 'r' )) { throw new Exception( 'Could not open file!' ); } // read file contents if ( ! $data = fread ($fh, filesize ($file ))) { throw new Exception( 'Could not read file!' ); } // close file fclose ($fh); // print file contents echo $data; } // catch errors if any catch (Exception $e) { print 'Something bad just happened...' ; } ?> ----output---- Something bad just happened... Example (tryncatcherror8.php):
  • 28. Catching up (cont..) If the file doesn't exist or is unreadable, the throw statement will generate an exception (basically, an instance of PHP's built-in Exception object) and pass it a message describing the error. When such an exception is generated, control passes to the first catch() block. If the catch() block can handle the exception type, the code within the catch() block is executed. If the first catch() block cannot handle the generated exception, control passes to the next one.
  • 29. Example (tryncatcherror9.php) < ?php // PHP 5 error_reporting (0); // try this code try {     $file = 'somefile.txt ';      // open file      if ( ! $fh = fopen ($file, 'r’ )) {         throw new Exception( 'Could not open file!' , 12);     }      // read file contents      if ( ! $data = fread ($fh, filesize ($file))) {         throw new Exception('Could not read file!', 9);     }     // close file      fclose ($fh);      // print file contents      echo $data; } // catch errors if any catch (Exception $e) {      print '<h2>Exception</h2>‘ ;      print 'Error message: ' . $e -> getMessage () . '<br />‘ ;      print 'Error code: ' . $e -> getCode () . '<br />‘ ;      print 'File and line: ' . $e -> getFile (). '(' . $e->getLine () . ‘)<br />‘ ;      print 'Trace: ' . $e -> getTraceAsString () . '<br /> '; } ? > ----output---- Exception Error message: Could not open file! Error code: 12 File and line: C:ampwwest2art12ryncatcherror9.php(12) Trace: #0 {main}
  • 30. Catching up (cont..) When you run this script, you'll see that the message generated by the exception handler contains: the descriptive data sent by throw, an error code (also sent by throw), the file name and line number where the exception occurred, and a stack trace indicating the exception's progress through the class hierarchy, if there is one. This data is generated by calling the Exception object's getMessage(), getCode(), getFile(), getLine() and getTraceAsString() methods respectively inside the catch() block. .
  • 31. Adding Some Class You can handle different exceptions in different ways, by sub-classing the generic Exception object and using more than one catch() block. Example(classerror10.php): Note that because PHP will always use the first catch() block that matches the exception type and because the generic Exception class matches all exceptions, the catch() blocks must be arranged in the order of most specific first .
  • 32. Example (classerror10.php) < ?php // PHP 5 // sub-class the Exception class class NegativeNumException extends Exception {} //class OutOfRangeException extends Exception {} class FloatException extends Exception {} // function to test a number function testNumber($num) { // float // trigger an exception if (is_float($num )) { throw new FloatException($num); } // negative // trigger an exception if ($num < 0 ) { throw new NegativeNumException($num); } // out of range // trigger an exception if ($num > 1000 || $num < 100 ) { throw new OutOfRangeException($num); } }
  • 33. // try this code try { testNumber (- 19 ) ; } // catch errors, if any catch ( NegativeNumException $e ) { print 'A negative number was provided (' . $e -> getMessage (). '). Please provide a positive integer between 100 and 1000.<br />' ; } catch ( OutOfRangeException $e ) { print 'The number provided is out of range (' . $e -> getMessage (). '). Please provide a positive integer between 100 and 1000.<br />' ; } catch (FloatException $e) { print 'The number provided is not an integer (' . $e -> getMessage (). '). Please provide a positive integer between 100 and 1000.<br />' ; } catch (Exception $e) { print 'Error message: ' . $e -> getMessage () . '<br />' ; print 'Error code: ' . $e -> getCode () . '<br />' ; print 'File and line: ' . $e -> getFile () . '(' . $e->getLine() . ')<br />' ; print 'Trace: ' . $e -> getTraceAsString () . '<br />' ; } ?> ----output---- A negative number was provided (-19). Please provide a positive integer between 100 and 1000.
  • 34. Here's another example, this one illustrating a more useful application - using the exception model in a user authentication class to provide easy-to-understand error handling Example(classerror11.php) Here, depending on the type of error, either a FileException() or an AuthException() will be generated - and handled by the corresponding catch() block
  • 35. Example (classerror11.php) < ?php // PHP 5 // class definition class userAuth { // define properties private $username; private $passwd; private $passwdFile; // constructor // must be passed username and non-encrypted password public f unction __construct($username, $password) { $this-> username = $username; $this-> passwd = $password; } // set .htaccess-style file to check for passwords public function setPasswdFile($file) { $this-> passwdFile = $file; } // perform password verification public function authenticateUser() { // check that the file exists if ( !file_exists ( $this-> passwdFile)) { throw new FileException( &quot;Password file cannot be found: &quot; . $this-> passwdFile); }
  • 36. // check that the file is readable if ( !is_readable ( $this->passwdFile )) { throw new FileException( &quot;Unable to read password file: &quot; . $this-> passwdFile); } // read file $data = file ( $this-> passwdFile); // iterate through file foreach ($data as $line) { $arr = explode ( &quot;:&quot; , $line); // if username matches, test password if ($arr [ 0 ] == $this-> username) { // get salt and crypt(), assuming encryption $salt = substr ($arr[ 1 ], 0 , 2 ); // if match, user/pass combination is correct if ($arr [ 1 ] == crypt ( $this-> passwd, $salt)) { echo &quot;User was authenticated&quot; ; // do some other stuff } // otherwise return exception else { throw new AuthException( &quot;Incorrect password&quot; ); break ; } } else { // could not find a username match // return exception throw new AuthException( &quot;No such user&quot; ); } } } // end class definition }
  • 37. // subclass exceptions class FileException extends Exception {} ; class AuthException extends Exception {} ; // try the code try { // create instance $ua = new userAuth ( &quot;joe&quot; , &quot;secret&quot; ) ; // set password file $ua -> setPasswdFile ( &quot;password.txt&quot; ) ; // perform authentication $ua -> authenticateUser () ; } // catch authentication failures, if any catch ( FileException $e ) { // print file errors print &quot;A file error occurred. &quot; . $e -> getMessage () ; } catch ( AuthException $e ) { // an authentication error occurred print &quot;An authentication error occurred. &quot; . $e -> getMessage(); // more normally, redirect to new page on auth errors, e.g. // header ('Location: login_fail.php'); } catch (Exception $e) { print &quot;An unknown error occurred&quot; ; } ? > ----output--- A file error occurred. Password file cannot be found: password.txt