PHP Custom Error Handling Continued

Right, so now we have the nice xHTML ready to slot in (you might need to have a look at previous posts in this series). Theoretically everything should work fine, but if you go back to the first part of the series you still have the problem of clearing up the useless data that PHP has outputted before the error, as it will be displayed before the doctype, invalidating the xHTML:

(useless data here)<!DOCTYPE html PUBLIC…

Here’s where the nifty bit comes in: using something called output buffering. I like to think of output buffering as pieces of paper stacked on top of each other. In this case we’ll only be using one piece of paper, but you could potentially have a lot more. By default your PHP scripts will write to a buffer (or piece of paper) and that buffer will be displayed automatically. You can interfere with this process by manually specifying your piece of paper for your script to write on, so that you can screw it up and throw it into the bin if need be. Simply call:

ob_start();

Before your output begins. Now that you have your buffer, you can throw it out as you please with:

ob_clean();

As I mentioned you can have more than one buffer (or piece of paper) so let’s have a look at this:

ob_start();

echo ‘This will display. ‘;

ob_start();

echo ‘So will this.’;

ob_start();

echo ‘No chance’;

ob_clean();

ob_end_flush();

Outputs:

This will display
So will this.

The only new thing you are seeing with is:

ob_end_flush();

All this does is to send the buffers to be displayed, and disable output buffering again. This can be combined with a custom error handler to display your errors as you intended:

function myErrorHandler ($errno, $errstr, $errfile, $errline, $errcontext) { (1)

switch ($errno) { (2)

case E_USER_ERROR:

ob_clean(); (3)

$page = &new Page(’An Error Has Occured’); (4)

$error=<<<EOD

t<h2>An Error Has Occured</h2>

<b>Error:</b> in $errfile on line $errline<br />

$errstr

EOD;

$page->addCentreContent($error); (5)

$page->addLeftContent();

$page->addRightContent();

$page->addFooter();

echo $page->returnPage();

ob_end_flush(); (6)

exit();  (7)

break;

}

}

  1. Define your custom error handler with “myErrorHandler”, this can be anything you want but you do have to follow the set parameters: “$errno”; what level of error you are handling like “E_USER_ERROR” “E_USER_NOTICE” or whatever, “$errstr”; the message you pass the function at call-time (more on this later), “$errfile”; the file where the error occurs, and “$errline”; the line number.
  2. Instead of making a code soup with if/else conditionals, it is much easier to use the switch. This takes a variable, so that you can compare it one at a time with the “cases” it could be. The “case” part of the switch basically serves as the “if ($variable == $action)” conditional. Though instead of starting with a curly bracket you use the colon, and finish with “break;”.
  3. Clean out the buffer we started before the output code.
  4. Instantiate the object made in Part 2, and build up the xHTML error page.
  5. Send the output to the browser
  6. Exit code execution so that any potential code after the error that outputs data doesn’t appear after the “</html>”

Now that the error handling function is ready, you have to make PHP recognise it as such, so it replaces its basic messages with your custom ones:

set_error_handler(‘myErrorHandler’);

Obviously this should be just underneath your error handling function. Now let’s have a look at a concept example:

echo ‘This is some table xHTML’;

if ($failedTableQuery) {

trigger_error(‘I am sorry but the data could not be retrieved from the database’,E_USER_ERROR); (1)

}

echo ‘I am making judgements on the above data’;

  1. Use “trigger_error” to make your errors

As you can see the benefits are two fold: the useless structure and the comments on the data are discarded, and you have a user friendly (well, as friendly as errors come) error. Some caveats: you will have to add further “cases” to your error handler function to deal with other types of php errors, and PHP 5 has different error handling capabilities that you should Google. Hope you found this series interesting, I welcome your comments. I think I’ll have a once over to check all the code works, but it’s nice to cross another thing off the list.

 

PHP Custom Error Handling

PHP has many built in error reporting levels, sometimes it is better to use these when your application fails on a fundamental level, specifically E_USER_ERROR.

Sometimes instead of handling fatal errors where they happen, I find bailing out into a global error handler more efficient. For instance take this concept example:

// This could be a failed

MySQL update or whatever

if (‘foo’ == ‘foo’) {

die(‘foo really shouldn’t equal foo’);

}

// This could be displaying the failed update

echo ‘this doesn’t work if foo != foo’;

Ok, so far so good, it may be poor man’s error handling, but at least it gets the job done. The user will never see the echo of the string that relies on foo!=foo, or the “failed update”.

It’s a hassle to continually code die() error messages, especially if you want to render the errors with pretty HTML; and there are clear benefits as to why you should do this:

  • Errors fit into the rest of your site, users get worried when look ‘n feel drastically changes, i.e. from nice CSS layout, to black and white critical mass of text.
  • It makes the site look more professional, and less buggy. You could even dress the error up to the point where it doesn’t look like one anymore. How about instead of “Error 404″, you could build:

I am sorry, but the page you were looking for has been moved. Here is a list of search results applying to the page you wanted:
-etc-
Use the search box below if you want to continue searching.
-etc-

  • You can create descriptive errors; instead of “Connection to MySQL Failed”, and a collective wtf from the users, you could change it to “I am sorry but an unforeseen error has prevented the information you requested from being retrieved from our database, please email the admin–etc.”
  • Custom error messages hide your code from being displayed, which could potentially leave you vulnerable.