Section 22.9. Custom Error Handlers


22.9. Custom Error Handlers

While assert( ) is a good function to make extensive use of, it only catches errors you were expecting. While that might sound obvious, it is quite crucialif an error you have not planned for occurs, how are you to find out about it? Never fearthere are two functions available to make your life much easier: set_error_handler( ) and error_log( ).

The set_error_handler( ) function takes the name of a user callback function as its only parameter, and it notifies PHP that any errors should use that function to handle them. The user function needs to accept a minimum of two parameters, but in practice you will likely want to accept four. These are, in order, the error number that occurred, the string version of the error, the file the error occurred in, and the line of the error. For example:

     function on_error($num, $str, $file, $line) {             print "Encountered error $num in $file, line $line: $str\n";     }     set_error_handler("on_error");     print $foo; 

On line four, we define the general error handler to be the on_error( ) function, then call print $foo, which, as $foo does not exist, is an error and will result in on_error( ) being called. The definition of on_error( ) is as described: it takes four parameters, then prints them out to the screen in a nicely formatted manner.

There is a second parameter to set_error_handler( ) that lets you choose what errors should trigger the error handler, and it works like the error_reporting directive in php.ini. However, you can only have one active error handler at any time, not one for each level of error. This code should explain it:

     function func_notice($num, $str, $file, $line) {             print "Encountered notice $num in $file, line $line: $str\n";     }     function func_error($num, $str, $file, $line) {             print "Encountered error $num in $file, line $line: $str\n";     }     set_error_handler("func_notice", E_NOTICE);     set_error_handler("func_error", E_ERROR);     echo $foo; 

As before, the error is that $foo isn't set; that should output a notice. On the surface, that looks as though we're assigning func_notice( ) to handle E_NOTICE-level messages and also assigning func_error( ) to handle E_ERROR-level messages. However, because we can only have one error handler at any one time, the second call to set_error_handler( ) replaces the first with one that only listens to E_ERROR messages.

The restore_error_handler( ) takes no parameters and returns no meaningful value, but it restores the previous error handler. There is only really one potential slip-up here, and that's when you accidentally call set_error_handler( ) twice with the same function name. If you've done this, calling restore_error_handler( ) won't make any change on the surface. Internally, it will be using the previous error handler, but as that happens to be same as the other handler, it will appear the same.

It's important to note that set_error_handler( ) does stack up previous error handlers neatly, as this script demonstrates:

     function func_notice($num, $str, $file, $line) {             print "Encountered notice $num in $file, line $line: $str\n";     }     set_error_handler("func_notice", E_NOTICE);     set_error_handler("func_notice", E_NOTICE);     set_error_handler("func_notice", E_NOTICE);     echo $foo;     set_error_handler("func_notice", E_NOTICE);     echo $foo;     restore_error_handler( );     echo $foo;     restore_error_handler( );     echo $foo;     restore_error_handler( );     echo $foo;     restore_error_handler( );     echo $foo; 

That will only really make sense once you've seen the output:

     Encountered notice 8 in C:\home\error.php, line 14: Undefined variable:  foo     Encountered notice 8 in C:\home\error.php, line 18: Undefined variable:  foo     Encountered notice 8 in C:\home\error.php, line 22: Undefined variable:  foo     Encountered notice 8 in C:\home\error.php, line 26: Undefined variable:  foo     Encountered notice 8 in C:\home\error.php, line 30: Undefined variable:  foo     PHP Notice:  Undefined variable:  foo in C:\home\error.php on line 34 

So you can see that we need to call restore_error_handler( ) enough times to fully unwind the stack of error handlers, until eventually the default PHP error handler has control and spits out the usual message.

The error_log( ) function is a great way to get error data saved to disk (or elsewhere) in just one call. At its simplest, you can pass error_log( ) just one parameteran error messageand it will log it for you. To get that, edit your php.ini file and set the error_log directive to a location Apache/PHP can write to. For example, /var/log/php_error would be good for Unix, and c:/windows/php_error.log is good for Windows.

With that done (don't forget to restart Apache, if necessary), we can go ahead and use error_log( ) in its most simple form:

     if (!mysql_connect("localhost", "baduser", "badpass")) {             error_log("Failed to connect to MySQL!");     } 

That will output data to our error log. It should also output actual execution errors into the filesomething like Warning: mysql_connect( ): Access denied for user: 'baduser@localhost' (Using password: YES) in C:\home\log.php on line 2. If not, enable log_errors in your php.ini file. PHP automatically inserts line breaks for you after each error.

The next two parameters really work in tandem, so I'll cover them together. The second parameteroddlytakes an integer to determine where your error should be sent: 0 sends it to the error_log (the default), 1 sends it by email using the mail( ) function, 3 is unused, and 4 saves it to a file of your choice.

The third parameter qualifies the second in that if you set the second parameter to be 1 (send error by email), the third parameter should be the email address of the recipient. Similarly, if you set the second parameter to be 3, parameter three should be the filename to save the error to. There is a slight twist to saving to a custom file, because PHP will not do any of the nice formatting for you like it does in the default error log. For example, it won't insert line breaks for you, and neither will it insert timestamps automaticallyyou need to insert all that yourself. This works out for the best, as it means you have complete control over your custom error log.

Here's a Windows example:

     if (!mysql_connect("localhost", "baduser", "badpass")) {             error_log("Failed to connect to MySQL!\r\n", 3, "c:/myerror.txt");     }



PHP in a Nutshell
Ubuntu Unleashed
ISBN: 596100671
EAN: 2147483647
Year: 2003
Pages: 249

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net