Spring Sale! Save 30% on all books w/ code: PLANET24
Web Dev + WordPress + Security

Advanced PHP Error Handling via htaccess

In my previous article on logging PHP errors, How to Enable PHP Error Logging via htaccess, we observed three fundamental aspects of preventing, preserving, and protecting your site’s PHP errors.

Prevent public display of PHP errors via htaccess

# supress php errors
php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
php_value docref_root 0
php_value docref_ext 0

Preserve (log) your site’s PHP errors via htaccess

# enable PHP error logging
php_flag  log_errors on
php_value error_log  /home/path/public_html/domain/PHP_errors.log

Protect your site’s PHP error log via htaccess

# prevent access to PHP error log
<Files PHP_errors.log>
 Order allow,deny
 Deny from all
 Satisfy All
</Files>

Now, in this article, we will explore these operations1 in greater depth, provide additional functionality, and examine various implications. First we will explore PHP error handling for production environments (i.e., for websites and applications that are online, active, and public), then we will consider error handling for development environments (i.e., for projects that are under development, testing, private, etc.).

Controlling the level of PHP error reporting

Using htaccess, it is possible to set the level of error reporting to suit your particular needs. The general format for controlling the level of PHP errors is as follows:

# general directive for setting php error level
php_value error_reporting integer

There are several common values used for “integer”, including:

  • Complete error reporting — for complete PHP error logging, use an error-reporting integer value of “8191”, which will enable logging of everything except run-time notices2.
  • Zend error reporting — to record both fatal and non-fatal compile-time warnings generated by the Zend scripting engine, use an error-reporting integer value of “128”.
  • Basic error reporting — to record run-time notices, compile-time parse errors, as well as run-time errors and warnings, use “8” for the error-reporting integer value.
  • Minimal error reporting — to record only fatal run-time errors, use an error-reporting integer value of “1”, which will enable logging of unrecoverable errors.

Of course, there are many more error-reporting values available, depending on your particular error-logging goals. For more information on logging PHP errors, refer to the Error Handling and Logging Functions page at php.net.

Setting the maximum file size for your error strings

Using htaccess, you may specify a maximum size for your PHP errors. This controls the size of each logged error, not the overall file size. Here is the general syntax:

# general directive for setting max error size
log_errors_max_len integer

Here, “integer” represents the maximum size of each recorded error string as measured in bytes. The default value is “1024” (i.e., 1 kilobyte). To unleash your logging powers to their fullest extent, you may use a zero value, “0”, to indicate “no maximum” and thus remove all limits. Note that this value is also applied to displayed errors when they are enabled (e.g., during development).

Disable logging of repeated errors

If you remember the last time you examined a healthy (or sick, depending on your point of view) PHP error log, you may recall countless entries of nearly identical errors, where the only difference for each line is the timestamp of the event. If you would like to disable this redundancy, throw down the following code in the htaccess file of your project root:

# disable repeated error logging
php_flag ignore_repeated_errors on
php_flag ignore_repeated_source on

With these lines in place, repeated errors will not be logged, even if they are from different sources or locations. If you only want to disable repeat errors from the same source or file, simply comment out or delete the last line. Conversely, to ensure that your log file includes all repeat errors, change both of the on values to off.

Putting it all together — Production Environment

Having discussed a few of the useful ways to customize our PHP error-logging experience, let’s wrap it all up with a solid, htaccess-based error-handling strategy for generalized production environments. Here is the code for your target htaccess file:

# PHP error handling for production servers
php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag track_errors on
php_value docref_root 0
php_value docref_ext 0
php_value error_log /home/path/public_html/domain/PHP_errors.log
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1
php_value log_errors_max_len 0

<Files PHP_errors.log>
 Order allow,deny
 Deny from all
 Satisfy All
</Files>

Or, if you prefer, an explanatory version of the same code, using comments to explain each line:

# PHP error handling for production servers

# disable display of startup errors
php_flag display_startup_errors off

# disable display of all other errors
php_flag display_errors off

# disable html markup of errors
php_flag html_errors off

# enable logging of errors
php_flag log_errors on

# disable ignoring of repeat errors
php_flag ignore_repeated_errors off

# disable ignoring of unique source errors
php_flag ignore_repeated_source off

# enable logging of php memory leaks
php_flag report_memleaks on

# preserve most recent error via php_errormsg
php_flag track_errors on

# disable formatting of error reference links
php_value docref_root 0

# disable formatting of error reference links
php_value docref_ext 0

# specify path to php error log
php_value error_log /home/path/public_html/domain/PHP_errors.log

# specify recording of all php errors
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1

# disable max error string length
php_value log_errors_max_len 0

# protect error log by preventing public access
<Files PHP_errors.log>
 Order allow,deny
 Deny from all
 Satisfy All
</Files>

This PHP error-handling strategy is ideal for a generalized production environment. In a nutshell, this code secures your server by disabling public display of error messages, yet also enables complete error transparency for the administrator via private error log. Of course, you may wish to customize this code to suit your specific needs. As always, please share your thoughts, ideas, tips and tricks with our fellow readers. Now, let’s take a look at a generalized error-handling strategy for development environments..

Putting it all together — Development Environment

During project development, when public access to your project is unavailable, you may find it beneficial to catch PHP errors in real time, where moment-by-moment circumstances continue to evolve. Here is a generalized, htaccess-based PHP error-handling strategy for development environments. Place this code in your target htaccess file:

# PHP error handling for development servers
php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag track_errors on
php_value docref_root 0
php_value docref_ext 0
php_value error_log /home/path/public_html/domain/PHP_errors.log
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1
php_value log_errors_max_len 0

<Files PHP_errors.log>
 Order allow,deny
 Deny from all
 Satisfy All
</Files>

For this code, we will forego the line-by-line explanations, as they may be extrapolated from the previous section. This PHP error-handling strategy is ideal for a generalized development environment. In a nutshell, this code enables real-time error-handling via public display of error messages, while also enabling complete error transparency for the administrator via private error log. Of course, you may wish to customize this code to suit your specific needs. As always, please share your thoughts, ideas, tips and tricks with our fellow readers. That’s all for this article — see you next time!

Useful Links

Footnotes

  • 1 For more information, check out the manual on Error Handling and Logging Functions at php.net
  • 2 Due to the bitwise nature of the various error-reporting values, the value for logging all errors continues to increase. For example, in PHP 5.2.x, its value is 6143, and before that, its value was 2047. Thus, to ensure comprehensive error logging well into the future, it is advisable to set a very large value for error_reporting, such as 2147483647.
  • 3 According to the PHP Manual on error_reporting, “Passing in the value -1 will show every possible error, even when new levels and constants are added in future PHP versions. The E_ALL constant also behaves this way as of PHP 6.” – Thus, the code in this article has been updated accordingly. Simply delete the commented-out line in the code and you’re good to go.

About the Author
Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
The Tao of WordPress: Master the art of WordPress.

22 responses to “Advanced PHP Error Handling via htaccess”

  1. Matías Orellana 2008/07/15 3:29 pm

    I must say thanks for this article, i’m hosted in a shared clustered server and i was having trouble finding some bugs withous the server log until i find this, Thanks!.

    However, later i found out that i wasn’t logging correctly until i compare the phpinfo() table with the “Master Value” and the “Local Value” this .htaccess was setting.

    The problem was the “true” and “false” options, in my hosting i needed to use “On” and “Off”, i don’t know if this is the default values of PHP but that did the trick.

    Thanks again for pointing us in the right directions!

    MoB.

  2. Perishable 2008/07/16 8:20 am

    Hi Matías! That is very helpful information and I appreciate you taking the time to share it with everyone. I have heard (and seen) of this situation before, and I am sure that others experiencing the same issue will benefit from the advice. In any case, I am glad you got everything configured and working properly. Thanks for the feedback! :)

  3. Jesper Pedersen 2008/08/12 6:24 am

    Thank you for the comprehensive article – definitely a worth reading.

    Just one little thing – As Matías also noted you shouldn’t use true and false when you’re setting boolean values. The PHP Manual states that you should use “php_flag” and “php_admin_flag” with the values “on” and “off”.

  4. Jeff Starr 2008/08/12 7:39 am

    Hi Jesper, glad you enjoyed the article. You (and Matías) are correct about using “on” and “off” instead of “true” and “false” for php_flag and php_admin_flag. I have edited the article to reflect this important information. Thank you for reiterating this point — it is greatly appreciated.

  5. In your secound example for the development environment the comment at the beginning still sais production you might wanna change that

  6. Jeff Starr 2008/11/16 3:48 pm

    @Uhu: Fixed! Thanks! :)

  7. Gowranga Chintapatra 2008/12/26 10:26 am

    Can I enable pear modules (Crypt/HMAC.php and Crypt/Http_request.php) through htaccess. If possible please let me to know how can I?. Actually I’ve installed Amazon Flexible payment in my site but I’m not getting the result and got an error in admin modules.php

    Thanks

  8. @Gowranga Chintapatra: I wish I could help you here, but unfortunately I am not familiar enough with Pear modules and Amazon code to be of any service on this one. Hopefully you will find useful information elsewhere!

  9. Kris Noble 2009/03/16 2:30 pm

    Thank you for this helpful post, saved me a lot of time!

  10. Jeff Starr 2009/03/22 7:39 am

    My pleasure, Kris — thanks for the positive feedback! :)

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
USP Pro: Unlimited front-end forms for user-submitted posts and more.
Thoughts
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
2024 is going to make 2020 look like a vacation. Prepare accordingly.
First snow of the year :)
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.