Tuesday, October 14, 2008

Throwing and catching exceptions

I recently had to review a web application that was written in PHP and was using Zend Framework to facilitate in the site setup.

One thing that I noticed was that although the code was well written, implementing coding standards and best practices on many of the classes, I did notice a wrong usage of throwing exceptions (the try - catch statements). Most of the exceptions were captured in global class, but nothing was done with it. In this blog post I will try to explain the concepts of bubbling exceptions so you can manage it all in one place.

If you're new to the concept of throwing and catching exceptions, take a look at the description on php.net as it explains you clearly what it's all about.

In short, throwing and catching exceptions is the good way to make sure your application doesn't do stuff it isn't supposed to do and leaving your application broken.

Example: division by zero
function divide($value)
{
    return 1 / $value;
}


This example will return a fatal error when $value is 0 (zero).

A better way would be
function divide($value)
{
    if (!$value) {
        throw new Exception('Division by zero is not allowed');
    }
    return 1 / $value;
}


This will cause your application to be aware that an exception is thrown. Of course you need to handle this in a proper way, that's why you use a try - catch statement.

function mymath($value)
{
    $result = 0;
    try {
        $result = divide($value);
    } catch (Exception $e) {
        echo "An exception occured: " . $e->getMessage();
    }
    return $result;
}


But when you're working on a web application, this might not be your desired action because you don't want to let your visitor know your application is broken. Instead, you want to handle exceptions your own way, by bubbling exceptions upwards so you can manage exceptions in one place.

Bubbling exceptions means that you check in your code fragment for an exception (in your try statement) and throwing this upwards (in your catch statement).

function mymath($value)
{
    $result = 0;
    try {
        $result = divide($value);
    } catch (Exception $e) {
        throw new Exception($e->getMessage());
    }
    return $result;
}


When you create your own exceptions, you can perform better management on your exceptions and act differently upon them.
Creating your own exception is pretty simple, you only need to extend the Exception base class.

class DivideByZeroException extends Exception {}

That's all to have your own exception in place. Now you can bubble it upwards again.

function mymath($value)
{
    $result = 0;
    try {
        $result = divide($value);
    } catch (DivideByZeroException $e) {
        throw new DivideByZeroException($e->getMessage());
    }
    return $result;
}


Now you can create your exception handler method to handle each exception on it's own and perform a specific action. In this case you might want to log these exceptions, but when accessing databases, files or webservices you might want to send out an e-mail to the administrator or developers. I am sure you can think of useful ways to handle different kind of exceptions.

Another good read that's related to this topic is a recent blog post of Patrick Allaert titled Readable PHP code #1: Return ASAP.
Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License.