【问题标题】:PHP: How to use set_error_handler() to properly deal with all errors except notices?PHP:如何使用 set_error_handler() 正确处理除通知之外的所有错误?
【发布时间】:2011-09-07 06:16:17
【问题描述】:

我对如何正确使用 set_error_handler() 感到困惑,php documentation 并没有真正帮助澄清。

我希望它通过电子邮件向我发送尽可能多的错误,通知除外。

我有以下代码

<?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.
}

?>

以上是我当前的设置set_error_handler('globalErrorHandler', E_USER_WARNING);,这似乎是错误的,因为它没有涵盖 trigger_error() 错误。我认为这是因为该参数应该是一个位掩码,而不仅仅是一个错误级别,但我不确定如何将其设置为最大数量的错误/信息(通知除外)。我见过使用E_ALL 的示例,但这实际上直接导致任何包含全局错误处理程序内容的代码对我来说出错。

无论如何,我如何使用 set_error_handler 以便我的自定义错误处理程序可以处理最大数量的信息(这样我可以在发生此类问题时直接收到自动电子邮件,而不必稍后查看日志)。

【问题讨论】:

    标签: php error-handling


    【解决方案1】:
    set_error_handler('some_handler',E_ALL & ~E_NOTICE & ~E_USER_NOTICE);
    

    或者,如果你真的想要全部,

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

    或者,您可以将其设置为使用所有错误,如果它们不在 error_reporting 中,则忽略它(您将其设置为与上述行相同的值,@ 运算符也可以工作):

    ....
    if(!($errno & error_reporting())) return true;
    switch($errno){
    ....
    

    【讨论】:

    • 等等,所以将它设置为 error_reporting() 的返回值也可以,对吧?我认为这正是我想要的,因为我已经报告了除通知之外的所有内容。
    • 是的,那么您可以省略第二个参数,并在那里检查error_reporting。
    • 哦,我的意思是作为第二个参数,例如set_error_handler('some_handler', error_reporting());
    【解决方案2】:

    省略第二个参数或传入默认E_ALL | E_STRICT(所有错误和严格错误,不要被这里的按位OR混淆)

    此外,您还可以通过此处演示的 register_shutdown_function()error_get_last() 技巧“捕捉”Fatal errorsHandle fatal errors in PHP using register_shutdown_function()

    【讨论】:

      【解决方案3】:

      $error_type 是您使用掩码设置的整数。要对除 E_NOTICE 之外的所有内容使用错误处理程序,您可以使用以下方法之一:

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

      如果您还想排除 E_USER_NOTICE,则:

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

      注意位运算符“&”、“~”和“|”的使用,参见PHP Bitwise operator manual

      请注意,如果某些错误发生在您的 set_error_handler 调用之前,或者是编译器错误(不太可能,但谁知道),它们将不会被拾取。见PHP set_error_handler documentation

      【讨论】:

        【解决方案4】:

        如何使用计划任务让服务器自动向您发送错误日志文件;而不是在您的应用程序中以这种方式处理它..

        【讨论】:

        • 已经通过 cron 上的 logcheck 和 logwatch 定期完成... ...这意味着在用户发生错误和我能够通过日志了解它,这就是为什么我需要一个更直接的响应机制来解决更重要的问题。
        • 这就是我使用自定义错误处理程序的原因——管理自定义日志记录(例如,使用完整的回溯)和通知。
        • 让我们以另一种方式混合它;制作一个文件比较小脚本,该脚本保留最后一个日志的副本,并与新日志进行检查,如果有更改会触发您发送电子邮件;否则它不会。频率可以设置得低一点;就像每 15 分钟左右.. 一个 1kb 的脚本不会造成太大的麻烦。否则;对于像上面这样的错误报告,您可以使用异常处理来处理所有类型的错误,并在异常捕获中执行您想做的任何事情,或者创建一个作为所有类的父级的异常类来为您完成这项工作。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多