====== Error Handling ======
This document describes error handling with the WACT framework, but much of this advise is applicable to PHP applications in general.
===== Configuration Settings =====
PHP has many configuration options that influence error handling behavior. See [[http://us3.php.net/manual/en/ref.errorfunc.php|PHP Error Handling and Logging Functions]] for a complete list.
Many PHP error configuration settings only work correctly and fully if set outside of the PHP script environment.
Configuration settings for error handling must be treated differently in the production and development environments. Error reporting requirements are higher in the development environment. Development oriented error reporting should not be used on production servers.
==== Production ====
The following error configuration settings are recommended for your production server. You may want to place these settings in a ''.htaccess'' file for your application. This way, the application will continue to perform as expected, even if the ''httpd.conf'' or ''php.ini'' files are altered, or if the application is installed on a server with an unknown configuration.
See the section on configuration settings in [[php:Writing Portable PHP Code]] for more information about where and how to set configuration settings.
=== Hiding Errors from the user ===
These settings prevent PHP's default error handler from showing error messages to the user.
php_flag display_errors off
php_flag display_startup_errors off
Hiding error messages can prevent internal application messages from revealing information to the user.
=== Logging errors ===
The following configuration setting directs PHP's default error handler to record error messages to an error log. This can help to track down the cause of any problems.
php_flag log_errors on
You may wish to specify a separate log file for your application.
php_value error_log /path/to/log
This can make it easier to work with an external log monitoring program, or expose the log in the application administration section in order to reveal errors which occur on a production system.
PHP errors which cause the termination of the apache process will not be directed to this log, but instead will be recorded in the apache error log and must be monitored separately.
=== Error Reporting ===
PHP's default error handler uses the ''error_reporting'' configuration setting to determine which errors to display (if ''display_errors'' is ''on'') or to log (if ''log_errors'' is ''on''). Many user error handlers will also respect the ''error_reporting'' configuration setting.
The error suppression operator @ temporarily lowers the ''error_reporting'' setting to ''0''. The current setting can be read with the [[phprn>error_reporting]] function.
In a production environment with the recommended ''log_errors'' set to ''on'' and ''display_errors'' set to ''off'', the ''error_reporting'' setting controls which errors are written to the log file.
A higher ''error_reporting'' setting is generally better. However, cramming the log with messages that will be ignored is not helpful. Choosing the right ''error_reporting'' level means balancing these tradeoffs. Some 3rd party libraries may require lower ''error_reporting'' levels.
Remember, that ''error_reporting'' in the ''http.conf'', ''.htaccess'', or ''php.ini'' level only affects errors that have not been suppressed by the error suppression operator ''@'', suppressed by a custom error handler via ''set_error_handler'', or suppressed by setting ''error_reporting()'' within the application (temporarily or permanently). It may be better to suppress expected messages with one of these techniques, rather than with a global setting that might also hide unexpected messages.
Errors of type ''E_ERROR'', ''E_PARSE'', ''E_CORE_ERROR'', ''E_CORE_WARNING'', ''E_COMPILE_ERROR'', and ''E_COMPILE_WARNING'' are uncatchable. They cannot be handled via a user level error handler within a PHP script. Thus, the only way to know if these errors have occurred in a program running on a production server is to set an ''error_reporting'' value that includes these types and to examine the error log.
The ''E_RECOVERABLE_ERROR'' is catchable, but if a user error handler is not installed and the error is not caught, the script is terminated. You may wish to include ''E_RECOVERABLE_ERROR'' in your ''error_reporting''.
Common error_reporting levels:
# E_ALL
php_value error_reporting W
# E_ALL | E_STRICT
php_value error_reporting X
# E_ALL ^ E_NOTICE
php_value error_reporting Y
# E_ALL ^ E_NOTICE ^ E_WARNING
php_value error_reporting Z
WACT is intended to work correctly with any ''reporting_level''.
=== Tracking Errors ===
With the ''error_tracking'' configuration setting ''on'', php will record the message of any error condition that occurs in the variable ''$php_errormsg''. The ''$php_errormsg'' variable retains its value until the next error occurs or until it goes out of scope. ''$php_errormsg'' will not be set if a user error handler has been registered with [[phpfn>set_error_handler]].
php_flag track_errors on
Sample benchmarks show that setting ''track_errors'' to ''off'' produces a negligible performance improvement. There is little measurable performance impact to leaving this setting ''on''. Obviously, the more errors that occur in your program, the greater the impact of this setting. Reducing the number of errors that occur has an order of magnitude more impact on the performance of error handling than this configuration setting.
You may wish to set the ''track_errors'' configuration on a local level for portability or maintenance reasons. See [[php:Writing Portable PHP Code]].
The message stored in ''$php_errormsg'' is influenced by configuration options controlling message display, such as ''html_errors''.
WACT does not require that ''track_errors'' be on.
=== Formatting Error messages ===
Several configuration settings control the formatting of PHP error messages. ''html_errors'', ''docref_ext'' and ''docref_root'' control the formatting of "docref" error messages. These effect the messages written to log files, passed to user error handlers, and placed in the ''$php_errormsg'' variable. It is recommended to disable this formatting on production machines.
php_flag html_errors off
php_value docref_ext 0 // correct?
php_value docref_root 0 // correct?
The ''error_append_string'' and ''error_prepend_string'' configuration settings control the formatting of error messages displayed by PHP's default error handler. They have no effect on logged messages, ''$php_errormsg'', or any user error handlers. They have no effect if ''display_errors'' is ''off''.
The ''log_errors_max_len'' controls the maximum length of any error messages logged or displayed by PHP's default error handler. The error message is truncated if it exceeds the specified length, unless the length is 0, in which case, the full error message is always used. Despite its name, this configuration setting effects errors that are displayed as well as errors that are logged.
The ''xmlrpc_errors'' and ''xml_rpc_error_number'' configuration settings are documented as part of the [[http://www.php.net/xmlrpc|xmlrpc]] extension, however, they are a part of core PHP. These settings are available even if the extension is disabled. These configuration settings direct PHP's default error handler to generate an xmlrpc representation of the error message.
//What is the impact of these settings on exception messages?//
=== Repeated Errors ===
The ''ignore_repeated_errors'' and ''ignore_repeated_source'' configuration settings direct PHP's default error handler not to display or log an error message if it is the same as the last error message that occurred. (Regardless of whether that message was displayed or logged). These settings can also suppress the assignment of ''$php_errormsg'' for "non-docref" style errors.
Using these settings on a production server is not recommended.
php_value_flag ignore_repeated_error off
Instead, suppress the error messages. (see section XXX)
=== Fatal Errors ===
The ''E_ERROR'', ''E_PARSE'', ''E_CORE_ERROR'', ''E_COMPILER_ERROR'' error types are fatal. This means that execution of the running PHP script is halted at the point at which the error occurs.
The user may see a blank page, or incomplete output. Pending [[http://us2.php.net/manual/en/ref.outcontrol.php|Output Buffering]] callbacks and [[http://us2.php.net/register_shutdown_function|register_shutdown_function]]s are still called even when a fatal error has occurred.
//Is there a way to issue a non-blank 500 style error page for a PHP fatal error?//
=== Monitoring Log Files ===
//Recommendations//
==== Development ====
The following error configuration settings are recommended for the ''php.ini'' file for your development environment:
display_errors = On
display_startup_errors = On
error_reporting = E_ALL | E_STRICT
===== Working with PHP Errors =====
From time to time, PHP detects that an error condition has occurred. These conditions can be of varying severity from ignorable to fatal. PHP classifies each error condition into one of several error types.
PHP's error handling functions are described in the [[http://us3.php.net/manual/en/ref.errorfunc.php|Error Handling and Logging Functions]] section of the PHP manual.
WACT does not use the PHP Error mechanism. However, most built-in PHP functions do, and other third party libraries may use this capability. Therefore, WACT does provide some tools for working with PHP errors.
==== Global Error Handling ====
When a PHP Error occurs, the global callback assigned with [[phpfn>set_error_handler]] is called. This callback handler can perform some sort of action. After the callback handler completes, execution continues from the point where the error occurs. (Unless the callback handler halts the program.)
A global callback handler has very little context specific information at its disposal. As a result, there is very little that a global error handler can do in response to an error.
One possibility to to log the error. Unless you have very special logging needs, you may want to leave the global error handler undefined and allow the built-in php logging mechanisms to handle this task, as explained in the section on PHP configuration options.
In a debugging environment, you may wish to augment the standard PHP error messages with additional debugging information. WACT provides an error handler for this purpose.
require_once 'wact/exception/debughandler.inc.php';
$handler = new WactDebugExceptionHandler();
$handler->install();
The ''install'' method on ''WactDebugExceptionHandler'' will call ''set_error_handler'' for you. You may also call the ''uninstall'' method to remove the handler object.
==== Suppressing Error Conditions ====
PHP can detect many error conditions. Some of these conditions might not even be considered errors at all. It is often necessary to suppress or ignore the error conditions that PHP discovers.
We don't want to fill up the error log with expected or unimportant messages.
=== Suppressing error conditions with error_reporting() ===
PHP maintains a global setting which indicates which types of errors should be ignored. See [[#error_reporting|Error Reporting]]. The [[phpfn>error_reporting]] function allows you to change the ''error_reporting'' configuration option in your program. You can do this to temporarily suppress certain kinds of errors.
$oldErrorReporting = error_reporting(E_NONE);
// Do something that might trigger an expected or unimportant error message
error_reporting($oldErrorReporting);
The error still occurs and the error handler callback is still called, however PHP's built-in error handler and most custom error handlers check the ''error_reporting'' setting.
=== The error suppression operator (@) ===
see [[http://www.php.net/manual/en/language.operators.errorcontrol.php|Error Control Operator]] in the PHP Manual. The error suppression operator works by temporarily setting ''error_reporting'' to ''E_NONE'' and then restoring the value when the operation has completed.
=== The scope of error suppression ===
Be careful with ''error_reporting'' and the error suppression operator. Calling functions while these operators are active can lead to suppressing unexpected as well as expected errors. For example:
@some_function(some_other_function());
In this code, if an error occurs while executing ''some_other_function'', that error will be suppressed. This can be very hard to debug. If the intent here is only to supress the errors from ''some_function'', this code should be re-written as:
$result = some_other_function();
@some_function($result);
Unexpected errors that occur while errors are being suppressed are difficult to track down. It can be easy to suppress errors for a broader scope than you might intend.
=== Don't suppress real errors ===
=== Defensive Code ===
It can sometimes be better to defensively check for an error causing condition, rather than allowing the condition to occur and then suppressing the error. For example:
$x = isset($var) ? $var : NULL;
instead of
$x = @$var;
Defensive codling prevents suppressing too many errors.
==== Reacting to Errors ====
There are three ways to react in context to an error that has occurred. One is to check the $php_errormsg. The other is to use an error handler that converts errors into exceptions, the third is to use a local error handler.
=== Checking for errors with $php_errormsg ===
=== Local error handlers ===
=== Converting errors into exceptions ===
==== Triggering your own Errors ====
Don't.
==== Using a Custom Error Handler ====
==== Writing an error handler ====
===== Working with Exceptions =====
See [[http://www.php.net/manual/en/language.exceptions.php|Exceptions]] in the PHP Manual.
==== Catching Exceptions ====
=== Wrapping Exceptions ===
=== Collecting Exceptions ===
==== Raising Exceptions ====
==== Testing Exceptions ====
==== Using a Custom Exception Handler ====
==== Writing an exception handler ====
===== References =====