Error reporting: Part II
Last month we looked at PHP’s extensive error reporting framework. This month we’ll be looking at customizing bug reporting and providing a lot more information for developers.
Python vs. PHP: Choose the language of your next project
Customized user error reporting
So far we have focused on bugs detected by the PHP breaker. However, once an application is finalized and tested, these bugs become secondary to the creation of standardized reports of user-generated bugs. PHP provides a framework for this. In the example below, we define our own error handler and use it in our functions:
01 <? 02 error_reporting(0); 03 function errhdlr($errno, $errstr, $errfile, $errline, $vars) 04 { 05 $ep = ""; 06 switch($errno) { 07 case E_ERROR: $ep = "Error"; break; 08 case E_WARNING: $ep = "Warning"; break; 09 case E_NOTICE: $ep = "Notice"; break; 10 case E_USER_ERROR: $ep = "Application error"; break; 11 case E_USER_WARNING: $ep = "Application warning"; break; 12 case E_USER_NOTICE: $ep = "Application notice"; break; 13 } 14 $ue = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE); 15 $err = "<p><b>$ep: $errstr ($errfile: $errline)</b></p>"; 16 if(in_array($errno, $ue)) { 17 $err .= "<p>Function variables: <br />". 18 "<pre>".var_export($vars, true)."</pre></p>"; 19 } 20 $err .= "<p>Backtrace: <br /><pre>".var_export(debug_backtrace(), true)."</pre></p>"; 21 echo $err; 22 } 23 function negate($num) 24 { 25 if(!is_numeric($num)) { 26 trigger_error("'$num' is not a number", E_USER_ERROR); 27 return 0; 28 } 29 if($num < 0) { 30 trigger_error("'$num' is already negative", E_USER_WARNING); 31 return($num); 32 } 33 return(- $num); 34 } 35 $olderrhdlr = set_error_handler("errhdlr"); 36 $num = negate("foo"); 37 $num = negate(-1); 38 $num = negate(1); 39 ?>
In line 02 we turn off PHP error reporting so that we can handle it ourselves. We then define our error handling function errhdlr(). This function takes five arguments: $errno, the type of error; $errstr, a string describing the error; $errfile, the file where the error occurred; $errline, the line where the error occurred; and $vars, an array representing the arguments to the function that generated the error.
Lines 05-13 determine what type of error occurred and define a string, $ep, that we use in our error report to let the user know how serious the error is. PHP can generate other errors, but for the sake of simplicity, we’ll only consider a few here. For a complete list of error types see http://www.php.net/manual/en/ref.errorfunc.php.
In line 14 we create an array of user-level errors to test our error type again. The reason is that only in these cases $var contains function arguments. Finally, on line 15 we create our error report, while on lines 16-19 we append a dump of function arguments, if any. In line 20 we generate a backtrace. This describes the path of the functions we took to get to the current line and is very useful for debugging unexpected errors. In line 21 we display the report.
Next, let’s create a basic negate() function that tries to negate the $num argument. There are two possible problems we can run into: $num is not a number, in which case an error has occurred; or $num is already negative, in which case the function was called incorrectly. In our case, these conditions generate an error or a warning.
To do this, we must first validate the argument. On line 25, we test whether $num is actually a number. If this is not the case, we create our bug report. This is done by calling the trigger_error() function. The first argument is an error string: $errstr in our error handler errhdlr(). The second argument is the error type. Note that it corresponds to one of the error types in errhdlr(). When viewed in a web browser, the error is displayed as follows:
Application error: 'foo' is not a number(/script.php: 27) Function variables: array ( 'num' => 'foo' )
Followed by a backtrace. In line 29 we test whether $num is already negative. If this is the case, we generate an alert. Finally, on line 35, we change the default error handler to errhdlr() with set_error_handler(). We then raise user errors by calling negate() with invalid arguments. That’s it for error handling. Next month I’ll have a first look at what’s new in PHP 5.
See more new articles in category: GUIDES