I am a programmer and architect (the kind that writes code) with a focus on testing and open source; I maintain the PHPUnit_Selenium project. I believe programming is one of the hardest and most beautiful jobs in the world. Giorgio is a DZone MVB and is not an employee of DZone and has posted 635 posts at DZone. You can read more from them at their website. View Full User Profile

Don't ignore errors

11.12.2012
| 2464 views |
  • submit to reddit

Bad stuff happens: database records go missing, remote services are inaccessible from time to time, and disks get full. But many language-level errors are caused by programming faults, not by external conditions: an important practice is managing errors to make sure they are detected, stored and resolved with minimal overhead.

Errors and exceptions

PHP was not originally an object-oriented language, and as such it produced many kinds of errors instead of exceptions. While some of them are compile-time errors and interrupt the whole PHP process execution, runtime errors are just a way to detect problematic scenarios. For example, consider the following PHP code:

$config = array('key'=> 'value');
var_dump($config['key2']);

Executing it under certain conditions (which we will see later) generates the following output:

PHP Notice:  Undefined index: key2 in /home/giorgio/prova.php on line 3
NULL

because accessing a not existing array index in PHP initializes the value to NULL and produces a Notice, an error of the lowest importance level.

However, the execution is not stopped as an exception would cause: runtime errors are more similar to compiler warnings than to exceptions. The code may still work as intended, but indeed accessing undefined variables or array indexes is problematic as you cannot distinguish the cases where it is done on purposes from the slip-ups. So the interpreter lets the script go on, unless it encounters a Fatal Error: the current request is served and the error will stimulate the programmer to solve the situation.

Configuration

Let me now recap some pretty standard configuration for your php.ini.

error_reporting = E_ALL | E_STRICT will signal errors for all possible conditions.

error_reporting = E_ALL is the PHP 5.4 version, which already contains E_STRICT.
Some programmers argue you should leaving Notices off in production, but I don't agree as it tends to encourage sloppy coding practices and to let you ignore errors. Most of the Notices are under your control as they are not initialized variables, indexes or fields; errors outside your own circle of influence like database connections gone awry are already at an higher level of importance.

display_errors = Off will make sure errors are never displayed to the user. Enabling this setting produces unfortunate responses:

PHP Notice:  Undefined index: key2 in /home/giorgio/prova.php on line 3
{
  "key": "value"
}

display_startup_errors = Off ensures the same behavior for configuration errors, such as php.ini directives with non-recognized values.

html_errors = Off means you don't need to display pretty errors in a browser, because you'll never see them inside a browser window again.

log_errors = On tells PHP to capture errors and writing them to a file. Since we do not display errors, this is the only setting that let us store them somewhere for later analysis; a file is also more persistent than a response's content, and as such can be grepped and parsed by different processes than the HTTP client.

error_log = /var/log/php_errors.log or error_log = syslog tell the interpreter which is the file.
log_errors_max_len = 0 does not impose a length after which error messages are cut (0 means infinite here).

Error handlers

PHPUnit uses set_error_handler () to convert all errors into exceptions: all notices or warnings in your test-covered code will be found and cause tests to fail; this practice ensures that unit tested code has a baseline quality level.
If you are programming strictly according to specification and want to interrupt execution any time an error is encountered, set up your own error handler too:

set_error_handler(
  array('PHPUnit_Util_ErrorHandler', 'handleError'),
  E_ALL | E_STRICT
);

The callable specified here should throw an exception containing information about the error, which is passed to it as arguments:

  public static function handleError($errno, $errstr, $errfile, $errline)
  {
  ...

The plan

You know now a bit more about PHP errors and how to treat them as real exceptions; they are a very handy tool and you should never ignore them.

Here is a plan for getting rid of errors in your PHP applications:

  1. set up the php.ini with the settings described earlier: all errors are logged but never displayed. Notice you're not changing behavior, as the errors would always happen; you're just choosing to store them somewhere instead of hiding them.
  2. Deploy.
  3. Monitor your php.log file to check for all the errors that are generated. If they're too many, raise temporarily the detection level to E_ALL & ~E_NOTICE, but once the file is empty lower it again.
  4. Once the file is empty at E_ALL (| E_STRICT) level, set up a custom error handler so that all errors are treated as exceptions. You can now afford to do so as errors are very few.

Once you have executed this plan, you will only have to deal with exceptions, and so your error handling code will be homogeneous and easy to write. Moreover, programming level errors such as undefined variables will never be present.

Published at DZone with permission of Giorgio Sironi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Filippo Tessarotto replied on Mon, 2012/11/12 - 8:54am

On new procjets I highly encourage to set the error handler into ErrorException thrower as the very first thing. This will also ease the error management, since you will not have anymore to manage errors, but only exceptions.

As Giorgio mentioned, in 2012 there is no reason why you want to hide (to you) the fact that your application is failing :)

Filippo Tessarotto replied on Mon, 2012/11/12 - 8:59am

Now I see that PHPUnit uses custom error Exception, that extends only \Exception.

I suggest to use the dedicated \ErrorException

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.