Write a custom error handler for PHP

Bobulous CentralCoding → PHP error handlers.

When writing PHP code for your web pages, it's important to see error messages as soon as they appear, and it makes sense to allow error messages to appear in the web page you're working on. But once your page goes live, visible to the public, it's best to hide error messages, partly to avoid advertising the fact your website has hit a snag, but also because error messages contain information that might allow malicious visitors to crack your site.

To avoid showing off PHP error messages to strangers, it's possible to configure your live server with the display_errors directive set to a value of zero, so that errors are not sent to the browser. The problem with this option is that errors on the live server then go completely unseen, which means that problems go unnoticed and probably unfixed.

A better option is to create custom error handlers, one for use on your test server, and one for use on your live server.

Error handler for testing

For your test environment, you just want to output PHP errors to the browser, so you can see them as you create and test your pages. An error handler like the following ought to do:

function output_errors($errno, $errstr, $errfile, $errline) {
    global $error_type;
    $error_name = (isset($error_type[$errno]) ?
            $error_type[$errno] : 'Unknown error code');
    $html = '<div class="php_error">'.
            '<p><strong>'.$error_name.'</strong><br />' .
            htmlspecialchars($errstr).'<br />'.
            'In <strong>'.
            htmlspecialchars($errfile).
            '</strong> on line '.
            htmlspecialchars($errline).
            '</p></div>';

    echo $html;
}

This will produce output very similar to the default PHP error handler, but you can modify it to add any extra information you want to know about every error that occurs.

Error handler for production

For your live environment, where the public should not be able to see your error messages, one way to make sure you are alerted to problems is to have the errors sent to a suitable email address. The following error handler will do the job:

function mail_all_errors($errno, $errstr, $errfile, $errline) {
    global $error_type;
    $error_name = (isset($error_type[$errno]) ?
            $error_type[$errno] : 'Unknown error code');

    $rtnl = "\r\n";  // shorthand for carriage return + newline
    $message = $error_name.$rtnl.$rtnl;
    $message .= $errstr.$rtnl.$rtnl;
    $message .= 'In '.$errfile.', on line '.$errline.$rtnl.$rtnl;
    $message .= 'Called from '.$_SERVER['PHP_SELF'];
    
    $headers = 'Content-type: text/plain; charset=utf-8';
    
    mail(SEND_ERROR_MAIL_TO, 'PHP Error message', $message,
            $headers);
}

Replace SEND_ERROR_MAIL_TO with the relevant email address, or define a constant with the same name. You may also need to change the charset value in the email header, if you are not using the UTF-8 character encoding.

As an alternative to having each error send an email, you could create a live error handler that appends messages to a log file (take a look at PHP's error_log function). However, people without their own server may not have permission to access server logs or create log files. So email may be the best way to make sure that errors are unseen by visitors without going unseen by the site developer. Just remember that plaintext email is not secure, so make sure that error messages won't reveal any critical details such as passwords.

Creating an error handler include file

For convenience, it's simple to create a PHP file that defines one or more error handlers, such as the above examples, and then calls the PHP function set_error_handler to set the active error handler. This file can then be included by other PHP scripts so that errors are handled the way you want.

Notice that the error handlers above both refer to an array called $error_type. This is simply an array that maps PHP error codes to strings that name the error encountered, making it easier to understand the type of error that occurred.

To see all of this put together, download my basic error handler include file, compressed either in gzip or ZIP format:

This include file is almost ready to use, but remember to define your email address in the constant SEND_ERROR_MAIL_TO so that the mail_errors function knows where to send error messages to. Then save the file in a suitable directory on your server and include the file once in your PHP scripts using include_once or require_once.

I couldn't find a way to securely autodetect whether the script is called from a test or live environment, so you need to make sure you change the call to set_error_handler so that the desired error handler is called on your live server, and then change it in the copy that stays on your test server. Be careful not to set the wrong error handler on your live server.

Bobulous CentralCoding → PHP error handlers.