Error vs Exception, Part 1

In this series, I’m going to take a look at both PHP’s error and exception models — what each is, how they work, and how and when to use the one or the other.

In this instalment, I will first attempt some definitions, and then take a closer look at PHP’s error handling model.

The Difference

Let’s attempt those definitions :

Error
When there is a mistake in the code, which one has to fix.
Example: to try and print the contents of a variable which doesn’t exist. The programmer can fix this error by declaring (and initializing) the variable.
Exception
When there is an irregular situation during the running of the program, which should have been expected as a possibility, and which the program should handle.
Example: when the database cannot be accessed because of some error on the server. The programmer cannot fix the problem as it doesn’t lie in his code, but the program should expect this exceptional situation as a possibility, and act accordingly.

Error Handling

Configuration

In PHP, there are a number of configuration directives that affect error handling specifically. Directives can be set in your php.ini file, or by using ini_set (not always). A boolean value can be set to either 1 or ‘on’ for true, and 0 or ‘off’ for false.

Types of Errors

The types of errors that the default PHP error handler reacts to/reports can be set with the error_reporting function or directive. One passes or sets as value a bitmask of those error type constants which are to be reported.
Examples might be :

// only E_ALL. Excludes E_STRICT for PHP < 6 as well as E_DEPRECATED and E_USER_DEPRECATED for PHP < 5.3
error_reporting(E_ALL);
// or by setting the directive
ini_set('error_reporting', E_ALL);

// E_ALL and E_STRICT.
error_reporting(E_ALL | E_STRICT);

// E_ALL but not E_NOTICE
error_reporting(E_ALL ^ E_NOTICE);

// All possible errors, always. A great default!
error_reporting(-1);

Display of Errors

Whether the reported errors are displayed on the screen or not, depends on the display_errors and display_startup_errors configuration directives. These should be set to false in a production environment (a live site), but can be set to true during testing to simplify debugging :

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);

Logging of Errors

When you do not display errors on the screen, you’d still like to know about them, and that’s where error logging is especially useful — the errors can be sent elsewhere, such as written to a log file, or emailed to an administrator. You instruct PHP to log errors with the log_errors directive, and to log to a file, you the set the error_log directive to the name of the file :

ini_set('log_errors', 1);
ini_set('error_log', 'logs' . DIRECTORY_SEPARATOR . date('Y-m-d', time()) . '_error.log');

Related directives

You might want to set these error-related configuration directives as well :

ini_set('log_errors_max_len', 0); // maximum length of log_errors (bytes). 0 = no limit
ini_set('ignore_repeated_errors', 1); // do not log repeating errors
ini_set('ignore_repeated_source', 0); // when ignoring repeated errors, source of error plays role in determining if errors are different
ini_set('track_errors ', 1); // place last error message in $php_errormsg
ini_set('html_errors ', 0); // no HTML tags in error messages

Examples

Set your errors to display on screen, and trigger the following errors to see what happens :

foreach ('foo' AS $bar) {};   // E_WARNING
echo $undeclared;             // E_NOTICE
$object->foo = 'bar';         // E_STRICT

You can see that an error is caused by a mistake in the code, which should be fixed.

Custom error handler

The errors above are handled by PHP’s default error handler, which we’ve set to report all errors — error_reporting(-1) — and print them to screen. But PHP also allows you to set up your own error handler to handle certain types of errors. You do it in the following way :

set_error_handler('a_callback_function', $error_type_bitmask);

The 'a_callback_function' above is the name of the function which will get called when an error occurs, and is of callback type. The $error_type_bitmask is the same type of bitmask as for error_reporting, as explained earlier, and determines the types of errors that the callback reacts to. So, for instance, one can set up a custom error handler to handle some error types, and the default error handler to handle the rest. In most cases though, if you go to the trouble of setting up a custom error handler, you’ll want it to handle all errors, log them, perhaps email a notice of the error to yourself if it’s a small site, then resume execution of the script, or perhaps stop execution for E_WARNING and output an informative message to the user.

One thing to note is that, if the error handler does not exit (a.k.a die), the script will continue executing as if there were no error. Also, whether the default error handler gets called or not, is determined by the return value of the custom error handler — if your handler returns false, the default handler will be called as well (that is if the default handler was instructed to respond to that type of error in the first place). And to prevent the default handler from being called, return true.

One can still ignore @-prepended errors in your custom handler by checking the value of error_reporting as I’ve explained in another article.

Exceptions

In Part 2 of this series I begin looking at the concept of an exception and see why they should be an essential part of your development repertoire.

Thanks for reading, comments are welcome!