More PHP Error Handling Tips

I gave a talk on Dealing with Errors at the PHP Unconference 2011 in Manchester, and notes were requested. So these posts cover the content of the talk, and more besides. This one covers suppressed errors, debug backtraces and multiple error handlers.

Suppressed errors

In PHP, you can indicate that some code should suppress any errors with an @ sign.

@print_r($this_variable_does_not_exist);

I personally don’t think you should do this – are you really sure you don’t care about any of the possible warnings that a function may generate? However I accept some programmers may think this is ok, and more to the point, you may have to collect errors from an application you did not write that does this.

Note that the error handler is still called in this case. But the error_reporting() function will return 0, so you can test whether errors were suppressed.

function error_handler($number, $message, $file, $line, $vars)  {
   if (error_reporting() == 0) return;
   die($message);
}
set_error_handler('error_handler');
@print_r($this_variable_does_not_exist);
print "OK";

Now ‘OK’ will be printed, as you would expect.

However there is a gotcha: If error_reporting is set to zero anyway, then all errors will be ignored. So make sure that error_reporting is set to a non-zero value before using this trick. If error_reporting is set to zero then I don’t know of a way to tell if errors are suppressed – if you do please let me know.

More information from errors

The debug_backtrace() function will provide you with a full stack-trace which can be very helpful for working out how the code got to the error.

<?php
function e($number, $message, $file, $line, $vars) {
   $x = debug_backtrace();
   print_r($x);
   die();
}
set_error_handler('e');
function b() { $hteu->oueoe(); }
function c() { b(); }
c();
Array
(
   [0] => Array
   (
      [file] => /media/692A-1D57/PHP Talk On Errors/debugBacktraceSample.php
      [line] => 8
      [function] => e
      [args] => Array
      (
         [0] => 8
         [1] => Undefined variable: hteu
         [2] => /media/692A-1D57/PHP Talk On Errors/debugBacktraceSample.php
         [3] => 8
         [4] => Array
         (
         )
      )
   )

The output is truncated to the 1st line only, but you can see it includes file, line, function and args – lots of data. But if you look closely you’ll see the function is set to ‘e’ – in other words, the exception handler itself is included. I find you can get a more accurate stack trace by taking off the top line and putting back a line with the information passed to the error handler.

<?php
function e($number, $message, $file, $line, $vars) {
   $x = debug_backtrace();
   array_shift($x);
   array_unshift($x, array('function'=>'?','file'=>$file,'line'=>$line));
   print_r($x);
   die();
}
set_error_handler('e');
function b() { $hteu->oueoe(); }
function c() { b(); }
c();

Array
(
   [0] => Array
   (
      [function] => ?
      [file] => /media/692A-1D57/PHP Talk On Errors/debugBacktraceSampleImproved.php
      [line] => 10
   )
   [1] => Array
   (
      [file] => /media/692A-1D57/PHP Talk On Errors/debugBacktraceSampleImproved.php
      [line] => 11
      [function] => b
      [args] => Array
   (
 

Finally, we previously talked about to how to catch FATAL errors with a shutdown function. In this case, debug_backtrace() will return the shutdown function only. I haven’t found a way to get a stacktrace when a fatal error occurs, and would love to know of one.

Multiple Error handers

You can only have one error exception at a time. When you call the set_error_handler() function it will return the name of the old error handler. You can store this and call it yourself from your error handler – thus allowing you to have multiple error handlers.

function e($number, $message, $file, $line, $vars) {
   global $old_error_handler;
   call_user_func_array($old_error_handler, array($code, $message, $file, $line, $vars));
}
$old_error_handler = set_error_handler('e');

Handling Errors and Exceptions leaving you puzzled? We work on an open source project to log problems, display a nice message to the user and email developers. We detect duplicates and let you track errors in tickets. Have a look at the ErrorReportingService module in Elastik!