Advanced PHP Error Handling via htaccess

Published Monday, January 14, 2008 @ 10:44 am • 22 Responses

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 operations 2 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 notices. 1
  • 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 to use, depending on your particular error-logging needs. 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
php_value error_reporting 999999999
log_errors_max_len 0

<Files /home/path/public_html/domain/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
php_value error_reporting 999999999

# disable max error string length
php_value log_errors_max_len 0

# protect error log by preventing public access
<Files /home/path/public_html/domain/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
php_value error_reporting 999999999
php_value log_errors_max_len 0

<Files /home/path/public_html/domain/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!

Footnotes

  • 1 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.
  • 2 For more information, check out the manual on Error Handling and Logging Functions at php.net

Dialogue

22 Responses Jump to comment form

1Louis

January 14, 2008 at 1:10 pm

That’s quite a good idea; too bad it’s not working on my shared hosting :/

2Perishable

January 16, 2008 at 10:44 am

Hi Louis,

As discussed elsewhere, it seems that PHP error logging has, for whatever reason, been disabled on your shared hosting account. I assure you, these are standard methods that will work (I use them myself) on any capable server.

3styx

February 19, 2008 at 4:37 am

Thanks for tips … it worked on my (only ftp access) server.

4Perishable

February 19, 2008 at 11:36 am

Sure thing, styx — thanks for the feedback! ;)

5Pete S.

March 18, 2008 at 6:40 am

Just wanted to say thanks for such a succinct and informative article. This is *exactly* what I needed to know. Very much appreciated.

6Perishable

March 18, 2008 at 9:43 am

My pleasure! I am very glad this article has proven helpful for you. Thank you for the positive feedback! :)

7Christelle

March 20, 2008 at 1:25 pm

Very nice job to put all the information together with adequate explanations. Thanks indeed !

8Perishable

March 22, 2008 at 5:45 pm

Happy to help, Christelle — thanks for the feedback! :)

9mmdesign

April 1, 2008 at 1:30 am

A bit earlier I came accross of a very basic error handling instruction.
But your articles gives so much more - an excelent in-depth tutorial for a newbie. And surprisingly it is easy to understand and it does work!! [5 stars!]
Thank you, Perishable

10Perishable

April 7, 2008 at 8:57 am

Thank you for the positive feedback, mmdesign! It is much appreciated! :)

11Ben Johnson

May 8, 2008 at 3:20 pm

Great article, and much-needed information, especially for new developers.

A couple of points of note, however.

1.) You should not use the

# specify recording of all php errors
php_value error_reporting 999999999

because that causes the error output that should ONLY be logged to be sent to the browser on many POSIX systems! Visitors to the site will see every single error PHP is logging, right in the browser window on every page!

Instead, you should use E_ALL, or a combination of the predefined constants. Using ANY integer value in this case is a bad idea, since they are subject to change. That is precisely why the constants exist!

2.) There is a small syntax error in your sample file (you forgot the php_value at the very bottom):

# disable max error string length
log_errors_max_len 0

should instead be

# disable max error string length
php_value log_errors_max_len 0

12Perishable

May 12, 2008 at 11:03 am

Hi Ben, thank you for sharing this information. I had no idea that POSIX systems behaved this way. Question: is it safe to use error_reporting given large enough reporting values on non-POSIX systems? I am trying to keep this article as general as possible, without requiring too much fiddling with various predefined-constant configurations. Perhaps simply replacing error_reporting with E_ALL would do the trick? In either case, I am going to revise the article to reflect this information and will post a followup comment here as well to signal the update.

Also, thanks for the catch on the missing php_value. There were two instances of this omission and both have now been corrected. Thank you! :)

13Matías Orellana

July 15, 2008 at 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.

14Perishable

July 16, 2008 at 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! :)

15Jesper Pedersen

August 12, 2008 at 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”.

16Jeff Starr

August 12, 2008 at 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.

17Uhu

November 15, 2008 at 1:48 pm

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

18Jeff Starr

November 16, 2008 at 3:48 pm

@Uhu: Fixed! Thanks! :)

19Gowranga Chintapatra

December 26, 2008 at 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

20Jeff Starr

January 1, 2009 at 10:42 am

@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!

Subscribe to comments on this post


Share your thoughts..

TopRead official comment policy

Contact Perishable Press

  • Contact Jeff via form

Search Perishable Press

About Perishable Press

Perishable Press is the virtual playground of Jeff Starr — visionary, founder and lead developer of Monzilla Media, a small web and graphic design company in the lush desert oasis of Moses Lake, Washington. Perishable Press features articles and tutorials on many aspects of digital design..

Read more..

Perishable on Twitter

better to have too many ideas and not enough time than the converse

Perishable on Tumblr

WordPress Tip for Multiple Themes

Sunday, 4 January 2009, 5:16 pm

If your site makes available multiple themes for users to choose from, remember to include the JavaScript (or any other required code) for any statistical applications that you might be using, such as Mint, Google Analytics, and so forth. I am not sure about the various WordPress statistics plugins, but they may need to be included as well. A good way to check if your stats plugin is tracking data across all themes is to either visit a few pages that you know others aren’t hitting, or else activate each of the alternate themes and check the source code of each one for the required code.

Earlier today, I realized that only several of my most recent themes included the required JavaScript for Mint and Google Analytics. I am now in the process of editing each of the 18 themes available for users at Perishable Press. Haven’t decided on whether or not both statistics apps are needed for all themes, but I will certainly be using at least one of them to keep an eye on everything.

Insane Christmas

Monday, 22 December 2008, 9:47 pm

For as long as I can remember, Christmas has always been a relatively peaceful affair. Sure there’s the usual holiday stress — traffic, shopping, presents, relatives, and all that goes with the preparation of a traditional celebration, but when it’s all said and done, you get to relax and enjoy the peace and harmony of gathering together and basking in the reason for the season: the birth of Christ.

This year, however, the stress factor has been kicked up a few notches, making for a rather insane Christmas if I do say so myself. In addition to the usual holiday chaos, we are currently purchasing a brand new home, and quickly realizing the incredible amount of work involved in the process. If you’ve ever bought a newly built home, you know exactly what I am talking about here.

Plus, as if all the paperwork, inspections, insurance, costs, and anxious anticipation weren’t enough to confound the usual holiday stress, we are also packing up everything, dealing with kids, working full-time jobs, and — beginning on Christmas Eve — moving into our new house.

It certainly is all a great joy and blessing to have such amazing things going on, but combined with the work that I do on the Web — blogging, designing, projects, helping people, and so on — it really becomes all too much rather quickly. We are doing are best to get through everything with our sanity intact, but I have to admit that this is the most insane Christmas I have ever experienced.

New (4G) Blacklist Now in Beta

Monday, 22 December 2008, 9:27 pm

Just a quick note to anyone interested in securing their websites against malicious activity, spam, and other nonsense. Several months after releasing my 3G Blacklist, I have finally begun work on the next incarnation of the blacklist: the 4G Firewall!

The first part of the blacklist is now ready for testing, and I plan on setting it up on Perishable Press within the next few days. While testing on my own site, I thought it would beneficial to also invite a few “beta” testers to run the code on their own site(s) as well.

So, if you have a site that receives its share of malicious attacks, and cracker exploits, drop me a line via the contact form at Perishable Press and I will send you the initial block of HTAccess directives. This version of the Blacklist is looking better than ever, and I look forward to releasing the complete version to the public early in 2009.

Thanks for the Free Traffic and Link Juice

Sunday, 7 December 2008, 1:26 pm

Just wanted to thank the fine folks at fafich.ufmg.br for all the free traffic and link juice. Thanks to their misapplication of my comprehensive canonicalization code, every non-canonical version of their 21,700 indexed pages points directly to my site, Perishable Press. This means that every one of their permalink URLs that is mistyped, lacks the “www” prefix, or contains the superfluous “index.php” file name is directed via permanent redirect directly to the home page of my site.

I have tried contacting the site owner(s) about this situation, but it has been over a week and I have yet to hear anything back. Hopefully, they will take notice soon and correct the issue by properly configuring their htaccess file, but in the meantime, I certainly don’t mind the extra link juice and free traffic! :)

No Plugin Needed for Feed Delay

Monday, 24 November 2008, 10:01 am

I recently saw a WordPress plugin that was designed to delay the publication of your WordPress feed by any specified time interval. While it is a good idea to carefully proofread your content before posting it, a plugin certainly is not required to do so.

As savvy WordPress users already know, WordPress has a built-in post-preview feature that enables authors to view their unpublished content as a published post. This enables authors to do any amount of proofreading and browser checking until they are satisfied with the results.

To do this, simply write your post as usual, and then click on the “Preview this post” button on the right-hand side of the screen. In older versions of WordPress (less than 2.5, I think), you actually need to save (without publishing!) the post first and then re-open it as if to continue editing. You will then see a “Preview »” link sort of hidden (due to poor CSS design) in the upper-right corner near the edit post field. Right-click on that link to open in new tab and you are good to go.

No extra plugin needed! :)

Read more on Tumblr..

Subscribe to Comments Recent Dialogue

  • Jeff Starr: Hi heywho, glad to hear you are doing well! ;) I wish I could join in the festivities.. it has been so long that I almost have forgot...
  • Rob Barrett: Thanks for posting about the Stealth Publish plugin -- just what I needed for my site. Works perfectly!...
  • Jeff Starr: Hi Chiwan, I got your email and have sent some information that may help you with this. Cheers, Jeff...
  • Chiwan: Hi. This is cool. So I can I replace the clock that comes with your Apathy theme with this clock? If that's not possible, how do ...
  • Brass Engraved: Thankyou very much for this, worked like a dream!...
  • Patrix: I'm using FeedBurner and the Feedsmith plugin for my filter blog, DesiPundit. I found your post via the WordPress page for RSS feeds ...
  • teddY: @Jessi Hance: Sorry to hear about your experience with Twitter spammers/flamers. I was once a victim of flamers and it sucks that peo...
  • heywho: Hey.... Very Nice...... I'm TOTALLY not a programmer..... but I have this thing I want to do...... so I just decided to start doi...
  • Rodrigo Nunes: NIce SEE MY BLOG http://designrn.wordpress.com/...
  • zubfatal: The Quintessential theme looks great to me, however when scrolling up or down on the page, it makes my laptop work harder than it sho...

Read more recent comments..

Attention: Do NOT follow this link!