17

I'm confused about how to use set_error_handler() properly, and the php documentation isn't really helping to clarify.

I want it to email me as many errors as possible, with the exception of notices.

I have the following code

<?php

if (TRAP_ERRORS) { 
// True on production, false in development, where errors are just echoed out.
    set_exception_handler('globalExceptionHandler');
    set_error_handler('globalErrorHandler', E_USER_WARNING);
}

function globalExceptionHandler($e) {
    //log and email stuff here
}

function globalErrorHandler($errno, $errstr, $errfile, $errline) {
    switch ($errno) {
        case E_NOTICE:
        case E_USER_NOTICE:
            $errors = "Notice";
            break;
        case E_WARNING:
        case E_USER_WARNING:
            $errors = "Warning";
            break;
        case E_ERROR:
        case E_USER_ERROR:
            $errors = "Fatal Error";
            break;
        default:
            $errors = "Unknown Error";
            break;
    }

    error_log(sprintf("PHP %s:  %s in %s on line %d", $errors, $errstr, $errfile, $errline));
    $msg = "ERROR: [$errno] $errstr\r\n".
        "$errors on line $errline in file $errfile\r\n";

    sendErrorEmail($msg);
    showErrorPage();

    exit(1);
}

function sendErrorEmail($p_errorMsg) {
    // Parse and sent out the error email...
}

function showErrorPage() {
    // Redirect to an error page.
}

?>

Above is my current setting set_error_handler('globalErrorHandler', E_USER_WARNING);, which seems to be wrong in that it doesn't cover trigger_error() errors. I believe that is because the argument is supposed to be a bitmask instead of just a single error level, but I am not sure how to set it to work for the maximum number of errors/information (except notices). I've seen examples that use E_ALL, but that actually directly causes any code that includes the global error handler stuff to error for me.

So anyway, how do I use set_error_handler so that the maximum amount of information can be handled by my custom error handler (so that I can get automatic emails directly when such problems occur, instead of having to review the logs later).

4 Answers 4

17
set_error_handler('some_handler',E_ALL & ~E_NOTICE & ~E_USER_NOTICE);

Or, if you really want all,

set_error_handler('some_handler',-1 & ~E_NOTICE & ~E_USER_NOTICE);

Alternatively, you can just set it to use all errors, and just ignore it if they're not in error_reporting (which you set to the same value as the above line, also, the @ operator works then):

....
if(!($errno & error_reporting())) return true;
switch($errno){
....
Sign up to request clarification or add additional context in comments.

3 Comments

Wait, so setting it to be the return value of error_reporting() would work too, right? I think that that's pretty much what I want, since I'm already reporting everything except notices.
Yup, then you can just omit the second parameter, and just have the check for error_reporting in there.
Oh, I meant as the second parameter, e.g. set_error_handler('some_handler', error_reporting());
3

Leave out the second parameter or pass in the default E_ALL | E_STRICT (all errors AND strictness errors, don't be confused by the bitwise OR here)

Additionally you can 'catch' Fatal errors by doing a register_shutdown_function() and error_get_last() trick demonstrated here: Handle fatal errors in PHP using register_shutdown_function()

Comments

2

The $error_type is an integer which you set using masking. To use an error handler for everything except E_NOTICE you'd use one of the following:

set_error_handler('globalErrorHandler', E_ALL ^ E_NOTICE);
set_error_handler('globalErrorHandler', E_ALL & ~E_NOTICE);

If you want to also exclude E_USER_NOTICE then:

set_error_handler('globalErrorHandler', E_ALL ^ (E_NOTICE | E_USER_NOTICE));
set_error_handler('globalErrorHandler', E_ALL & ~E_NOTICE & ~E_USER_NOTICE);

Note the use of the bitwise operators "&", "~" and "|", see PHP Bitwise operator manual.

Be careful, some errors will not be picked up if they occur before your set_error_handler call, or are compiler errors (unlikely, but who knows). See PHP set_error_handler documentation.

Comments

0

How about using scheduled tasks to let the server send you the error log files automatically; instead of handling it this way within your application..

3 Comments

Already done on a periodic basis via logcheck and logwatch on a cron... ...which means that there is a delay between when an error occurs for a user, and when I would be able to find out about it via logs, which is why I need a more immediate response mechanism for more important issues.
This is pretty much why I've used custom error handlers -- to manage custom logging (with full backtrace, for example) and notifications.
Lets blend it the other way; make a file comparison small script which keeps the copy of the last log and checks it with the new one if there is a change it triggers u an email; otherwise it dosen't. Frequency could be set a little low; like every 15 minutes or so.. A 1kb script wont cause much trouble. Otherwise; for error reporting like above you may use exception handling to catter for all types of errors and do whatever u want to do in exception catch or make an exception class which is parent of all your classes to do that job for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.