Debugging in PHP: Handling Uncaught Exceptions

“Indicating a Problem with Exceptions” on page 108 explained the basics of how PHP uses exceptions, and Example 6-8 showed what happens if an exception is thrown but not caught: your PHP program stops running and the PHP engine prints out error information and a stack trace (the list of functions that have called one another at the point where the program has stopped).

While you should always include try/catch blocks around any code that might throw an exception, in practice it can be difficult to meet that goal perfectly. You might be using a third-party library and unaware of exceptions it throws, or you might just make a mistake and forget a situation where your own code can throw an exception. For these situations, PHP gives you a way to specify a special exception handler that will get called if your code doesn’t handle an exception. This exception handler is a good place to log information about the exception and present information to your program’s user that is friendlier than a stack trace.

To use a custom exception handler for otherwise uncaught exceptions, do two things:

  1. Write a function that will handle the exception. It takes one argument: the excep­tion.
  2. Use set_exception_handler() to tell the PHP engine about your function.

Example 12-8 sets up an exception handler that prints a nice error message for a user and logs more detailed information about the exception.

Example 12-8. Setting up a custom exception handler

function niceExceptionHandler($ex)

{

// Tell the user something unthreatening

print “Sorry! Something unexpected happened. Please try again later.”;

// Log more detailed information for a sysadmin to review

error_log(“{$ex->getMessage()} in {$ex->getFile()} @ {$ex->getLine()}”);

error_log($ex->getTraceAsString());

}

set_exception_handler(‘niceExceptionHandler’);

print “I’m about to connect to a made up, pretend, broken database!\n”;

// The DSN given to the PDO constructor does not specify a valid database

// or connection parameters, so the constructor will throw an exception

$db = new PDO(‘garbage:this is obviously not going to work!’);

print “This is not going to get printed.”;

In Example 12-8, the niceExceptionHandler() function uses print to give the user a simple message and error_log(), along with methods on the Exception object, to log more detailed technical information for review. The call to set_exception_handler() with the niceExceptionHandler argument (as a string) tells the PHP engine to give any unhandled exceptions to that function.

The output from Example 12-8 is:

I’m about to connect to a made up, pretend, broken database!

Sorry! Something unexpected happened. Please try again later.

And the logged error information is:

could not find driver in exception-handler.php @ 17

#0 exception-handler.php(17): PDO->     construct(‘garbage:this is…’)

#1 {main}

This prevents the user from seeing confusing technical details that could potentially leak secure information (such as database credentials or file paths) but stores that information in the error log for review.

A custom exception handler doesn’t prevent your program from stopping after the exception is handled. After the exception handler runs, your program is done. That’s why, in Example 12-8, the This is not going to get printed. line is never printed.

Source: Sklar David (2016), Learning PHP: A Gentle Introduction to the Web’s Most Popular Language, O’Reilly Media; 1st edition.

Leave a Reply

Your email address will not be published. Required fields are marked *