jump to navigation

An Overview of Exceptions in PHP July 5, 2014

Posted by Tournas Dimitrios in PHP.

php exception graphAn Exception, as the name implies, is any condition experienced by a program that is unexpected or not handled within the normal scope of the code. Exception handling is prevalent among many popular languages ( Java , C++ , C# , Python to name a few) , it was added to PHP with the version 5 release.  When an Exception occurs, PHP’s default behavior is to :

  1. abruptly stop the flow of the program (code following the exception-event will not be executed),
  2. instantiate an object of type “Exception”  and passing valuable information into the object regarding the origin of the error (file , line , error-code, error-message).
  3. display a “Fatal error” message.

We can overwrite this default behavior though, by catching the Exception object, interfering with a custom — predefined — task (ie Logging the event , displaying a user friendly message) and continuing the program flow as nothing has happened. Actually there are two methodologies to catch exceptions (we’ll get into more details later on)

    A few keynotes :

  • Beside the fact that a user facing a “Fatal error” cannot perceive it as a pleasant experience, it might be a serious security risk (revealing sensitive information).
  •  A favorite expression used by developers is : “An Exception is thrown“.
  • Not only PHP’s interpreter can “throw” exceptions, also developers can “throw” exception-events programmatically by using PHP’s “throw” construct .
  • PHP has a long list of built-in exception classes .
  • An exception object can be catched with the “try/catch” construct . Sometimes it is helpful to catch an exception, look at some of its properties, and then re-throw it again. This is often useful to check an error code and decide whether it should be fatal.

Before we dig into practical examples, let’s first present a few characteristics of PHP’s exception mechanism.

  • The Exception class is the base for all exceptions. We can extend this class to define custom exception classes. (there is no limit how deep the class hierarchy goes). PHP’s built-in SPL library has done this for us, it created a long list of descendants of the Exception class that can be used in any application, nothing stops us to create our own exception classes though (there is one prerequisite though, the custom exception class must be a descendant of the Exception class ). SPL exceptions are quite similar to the base class, but they  fit the more specific conditions of an exception condition (they describe much better the error, so to speak).
    The picture below shows all PHP’s built-in Exception Classes.PHP exception chart
  • As seen in the picture above, SPL exceptions are classified into two groups (LogicException and RuntimeException). The purpose of this classification is to allow us to differentiate between compile-time logical exceptions and exceptions caused by bad data being passed to the application (run-time errors). While run-time error can be used to inform a user about an error condition he/she might be responsible (for instance, he/she submitted an invalid email address and triggered an UnexpectedValueException), compile errors are only the responsibility / interest for the developer (usually these kind of errors are logged, for  debugging purposes).
  • The constructor of the Exception Class optionally takes an error message and an error code. This error code can be used later on to distinguish the origin of the Exception event.
  • Once constructed, an Exception object knows several key things: where it was constructed (file and line), the error message and the error code.
  • the exception inheritance tree has no limit, it can have as many levels deep we desire. An exception-event will automatically travel up the call chain until it reaches the level that catches it. If it’s not caught on any level, program execution terminates due to an uncaught exception. The whole point of exceptions is to be able to have exception-errors bubble up.

Catching Exceptions:

Method-1 : Defining an uncaught exception handler :
As aforementioned, PHP’s default behavior to exception-events is to stop the execution of the script and displaying a “Fatal error” message. For a couple good reasons (which we have already mentioned) the message can be customized  by defining a global exception handler function. The set_exception_handler() function defines what to do when an exception makes it all the way up your call stack to the main function entry without being caught.

function exception_handler($exception) {
  echo "Uncaught exception: " , $exception->getMessage(), "\n";

set_exception_handler(function($exception) {
  echo "Uncaught exception: " , $exception->getMessage(), "\n";

throw new Exception('A custom error message');
echo "Not Executed\n";

The exception handler can be defined as a function, the name of the function is then passed as parameter into set_exception_handler . Alternatively, an exception handler can be defined as anonymous function directly into set_exception_handler.
Method-2: Isolating and catching exceptions :
A better approach for exception handling is to isolate exceptions into a self-contained block so that the program flow will not stop in the event an exception occurs. This is achieved with the try/catch block .

try {
    // code goes here
    throw new Exception('A custom error message');
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
echo "This will be excecuted ...... \n";

From PHP >5.5 try/catch blocks can have a “finally” clause which will run any code it contains. A “finally” clause is always executed before leaving the try statement, whether an exception has occurred or not.

Type-hinting and Exceptions :

By using type hinting and multiple catch blocks, we will be able to catch certain types of errors.

class TwitterAuthException extends Exception {} 

try {
    // code goes here
    throw new TwitterAuthException('Failing to authenticate');
} catch (TwitterAuthException $e) {
    echo 'Caught TwitterAuthException : ', $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
echo "This will be excecuted ...... \n";

Keep your eyes on exception hierarchy when implementing multiple catch blocks. A practical example will better describe my thoughts.

class FacebookAuthException extends Exception {}
class FacebookSessionExpiredException extends FacebookAuthException {} 

try {
    // code goes here
        throw new FacebookSessionExpiredException('Session is expired');

    } catch (FacebookAuthException $e) {
        echo 'Caught FacebookAuthException : ', $e->getMessage(), "\n";
    } catch (FacebookSessionExpiredException $e) {
        echo 'Caught FacebookSessionExpireddException : ', $e->getMessage(), "\n";
    }catch (Exception $e) {
        echo 'Caught exception-->: ',  $e->getMessage(), "\n";
echo "\n This will be excecuted ...... \n";

Let’s describe the bug : A “FacebookSessionExpiredException”  was thrown programmatically to emulate a real scenario, the exception-event is catched by the first “catch block” ( FacebookSessionExpiredException is a descendant of FacebookAuthException). First catch will stop the exception-bubble effect and the catch block of FacebookSessionExpiredException will never been reached.
A bit of statistics (ie how do frameworks use exceptions) :
Exceptions are used extensively on almost all frameworks/libraries . The following table shows the total counts of custom exception classes and how many times the keyword “throw” is used inside a few popular frameworks/libraries . Keep in mind, the results were taken just to compress my curiosity and probably have sufficient tolerance in their accuracy. Anyway , at the end of the table are the commands that have been used on my Centos machine to extract the values given .

Framework Custom Exception Classes times “throw” was used
Symfony 2 192 1920
Zend Framework2 144 2692
Laravel4 132 2033
Sylex1.* 48 298
Doctrine2 37 875
Twig (with extensions) 4 165
 “throw” in files : grep -r “throw” . |grep -v ‘*’ |wc -l
custom exception files: find . -iname “*exception*.php” | wc -l

Final thoughts :
One common mistake novices make is to use exceptions for every type of error situation. Exceptions were built for exceptional situations , use exceptions when you can detect an event or condition in a unit of code that prevents any further execution. Good examples include:

  • database connection errors
  • unfulfilled web service calls
  • file-system errors (such as permissions, missing paths, and so on)
  • parse errors (for example, when parsing configuration or template files)

Links :


No comments yet — be the first.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s