June 6, 2011
The Ultimate PHP Error Reporter
A visitor to one of my websites mentioned in passing that the contact form had given him an error. When pressed to give more details, none were forthcoming. It turned out that the contact form had developed a fatal error when the server was last updated four and a half months earlier. During all that time the contact form was unavaliable and who knows how many visitors were turned off by the malfunctioning website. This situation is unacceptable. Human errors do happen but we need tools to catch them in the shortest possible time. Webmasters and administrators need a proactive error reporting method. While writing the phpErrorReporter code I discovered another problem with the server (different website) that likely was also four and a half months old. This second error needs a different reporting function which is my next software project.
Websites have become an integral part of the operation of many businesses and one can no longer afford downtime. Unfortunately, many errors are silent as illustrated above and unless some kind soul notifies the webmaster, they can go undetected for months causing uncounted losses for the business they form a part of.
Web error logs are no longer sufficient. Web hosting is now so reliable that trying to find fatal errors perusing them is worse than looking for needles in haystacks. Browser alerts, while useful feedback for users and specially for hackers, do not actively notify webmasters of the problem. Worse, detailed error messages displayed in browsers enable hackers to break into systems more easily. Production websites should have error reporting turned off for this reason.
The solution is an active error handler that sends email alerts to the webmaster or to the system administrator. In addition, the error handler should keep a complete error log that can be inspected at will and it must also generate feedback for the website's visitors without giving out excess information that enables hackers to break in. With this in mind I went googling for solutions, see the links below.
I used Tony Marston's 2003 article as my starting point. I quickly discovered that it does not catch the most important errors, the fatal ones. It says so right in the php manual on the set_error_handler()
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
Googling on I discovered the register_shutdown_function()
which lets you check if an error is shutting down the process. With those two functions I could catch all the errors but one problem remained, how to have each php process use the code. Editing each php script to make it use the phpErrorReporter code would be a huge and error prone process. Another article found with the help of Google solved this problem, Advanced PHP Error Handling via htaccess
by Jeff Starr suggested using php's auto_prepend_file
facility. If activated by htaccess in the document root, it would cause all php scripts to use it.
The phpErrorReporter code is heavily commented so I won't go into the details of how it works. Suffice it to say that it consists of two functions, an error handler and a shut down handler and some php directives in the htaccess file. You can download the code in the link below my signature.
The other silent bug I mentioned above was that files with two file extensions (myCode.php.tgz) stopped downloading and instead were giving HTTP 500 errors. I'm thinking of adding a similar error reporter to my custom 500 error pages. Next on the to-do list is some back end code to manage the php error logs created by phpErrorReporter.
Customising the PHP error handler
by Tony Marston (2003)
Advanced PHP Error Handling via htaccess
by Jeff Starr (2008)
Many useful user contributed notes in php manual (2011).
Share this article with your followers