Version 4, last updated by pagchen at November 07, 2011 18:00 UTC

This wiki has been updated for version 0.7-alpha4

1. Catch only what you need

Catching exceptions is like catching fish: although you can always throw it back, it's better to use the right bait to begin with. Add as many different exception classes as you need. That will make it easier to catch only the ones you are specifically looking for.

Don't:

try {
   // do something
}
catch (Exception $e) 
{
   if($e->getMessage() == 'Division by zero') {
       echo "Don't divide by zero, it hurts my CPU!";
   } else {
       throw $e; // rethrow if it's not the exception we're looking for
   }
}

Do:

try {
    // do something
}
catch (DivisionByZeroException $e) { // Only catch what we need
    echo "Don't divide by zero, it hurts my CPU!";
}

2. Exceptions are not for control flow

When you expect a certain situation to occur, it is not an exception, it is part of your control flow. Only for error conditions, aka situations that should not happen, you use exceptions.

Don't:

Don't use exceptions for authentication, validation, ...

try 
{
    if(!$user->isAuthenticated()) {
        throw new NotAuthenticatedException($user->name.' is not authenticated');
    }
    // do stuff...
}
catch( NotAuthenticatedException $e) {
    echo "Sorry, looks like you can't do that: ".$e->getMessage();
}

In the above example, an exception is being used for something that you do expect to happen. A user might try to do something he is not allowed to. This is not an error condition, so it should be handled with regular control flow structures:

if($user->isAuthenticated()) {
    // do stuf...
} else {
    echo "Sorry, you can't do that.";
}

Do:

Use exceptions for error conditions such as bad syntax, missing files, wrong file permissions, ... in short all the kind of things you used to use die for.

try 
{
    if(!file_exists('important.php')) {
        throw new FileMissingException("Couldn't find important.php. Maybe the application wasn't installed correctly?");
    }
    require 'important.php';
}
catch( FileMissingException $e) {
    echo $e->getMessage();
    die; // can't continue without this file
}

In the above example, this situation should never happen, unless important.php wasn't installed correctly to begin with. If that's the case, there's no way the normal operation of the script can continue.

3. Do something useful with your catches

Often you'll want to use exceptions to help users (or yourself). So far, the above examples show small code blocks, but in reality, you might want to catch exceptions at a lower level, for example by wrapping your complete application in a try/catch statement.

Do:

try {
     KService::get('com://admin/harbour.dispatcher')->dispatch($view);
}
catch(FileMissingException $e) 
{
     // Redirect the user to the installation page, so he can reinstall the app
     $app->redirect($installation_page, $e->getMessage());
}
catch(SqlBadSyntaxException $e) 
{
    send_email(
        'developer@example.com',
        "Dear developer, you have malformed sql statements in your app: ".$e->getMessage()
    );
}

4. Learn more

This is a good resource on exception best practices: http://framework.zend.com/wiki/display/ZFDE/PHP+Coding+Standard+%28draft%29#PHPCodingStandard%28draft%29-Exceptionbestpractices