Saturday, March 5, 2011

PHP: Exceptions in action

How to handle errors in the code flow?

Object oriented programming offers a useful way to get through this problem. When you come across a condition where you must generate an error (when checking inputs at form validation for example), you can throw an exception. See the example below:

  • /* a function what will throw an exception if the $input is invalid */
  • function check_input($input=NULL) {
  • if( !is_string($input) ) throw new Exception('Invalid input',1);
  • }
  •  
  •  
  • /* later in the code */
  • try {
  • /* it will throw an exception */
  • check_input(4);
  • check_input('hi there');
  • }
  • catch (Exception $e) {
  • echo $e->getMessage();
  • }

When using exceptions, your code must contain the following things:
  • a try {} block: this is where you trigger the exception
  • a throw new Exception() call: this is how you trigger the exception
  • one or more catch() {} blocks: this is where you handle the exception.
The check_input() function will throw an exception if it is called with a non-string parameter. I've called it twice in the try block. If an exception is thrown, the code flow stops running inside the try block. This is where the catch block becomes important, because this is where the code continues running if there is a corresponding catch block for the thrown exception class.The $e variable will be our exception object and we can get the values from it. If you wish to see the default class for exception objects, please visit the PHP Exception manual. Initialize an exception as follows:

  • throw new Exception('Your message', <your integer number>);

Let me extend our first example:

  • /* a function what will throw an exception if the $input is invalid */
  • function check_input($input=NULL) {
  • if( !is_string($input) ) throw new Exception('Invalid input',1);
  • if( strlen($input)>10 ) throw new Exception('Too long input',2);
  • }
  •  
  •  
  • /* later in the code */
  • try {
  • /* it will throw an exception */
  • check_input(4);
  • }
  • catch (Exception $e) {
  • echo $e->getMessage();
  • switch( $e->getCode() ) {
  • case 1:
  • {
  • /* do something here for code 1 */
  • /* let's just echo the message */
  • echo $e->getMessage();// 'Invalid input'
  • } break;
  • case 2:
  • {
  • /* do something else here for code 2 */
  • /* echo the error message and something else */
  • echo $e->getMessage();// 'Too long input'
  • echo 'Give a shorter string.';
  • } break;
  • default:
  • {
  • /* do something default here */
  • } break;
  • }
  • }

In the extended example, I modified the code to throw another exception if another condition is met. Note that there is two exception and one catch block. The reason why I can do this in the code is because we handling one exception class called Exception. PHP has another default Exception class called ErrorException. If you wish to use different exception classes in your code, you must have a corresponding catch block for them. (You can read about this in my next article.)

When I constructed the exception objects, I gave them different codes in the second parameter. By the $e->getCode() method, you can get the corresponding code for the exception object and for example, you can put it to a switch-case statement where each case handles a separate error.

Note that if you throw an exception without putting it into a try block, your code ends in a fatal error.

In my next article I'm going to write about how to extend the default Exception class and how to write your own classes for handling errors rather then using switch statements.

I hope I've helped.

Zsolt Szivák