自定义错误手法函数,不捕获错误控制的流量(带@)

Custom error handlig function to not catch errorcontrolled flow (with @)

提问人:BakirG 提问时间:9/27/2023 更新时间:9/27/2023 访问量:27

问:

我制作了自定义错误和异常处理程序函数(在核心文件中)并通过以下方式设置它们:

set_error_handler('custom_error_handler');
set_exception_handler('custom_exception_handler');

在代码的其他地方,我从 $_GET 超全局请求中验证 GET 参数。即使某些 GET 变量可能未传递/设置,我也会验证并存储它们。为了避免用户错误,我放置了 errorcontrol PHP 运算符,即 '@',它成功地向用户隐藏了不必要的错误。

另外,我熟悉“@”运算符的工作原理,基本上它会在表达式具有该运算符的行上将错误报告设置为 0,然后重新打开它。

我的目标是仍然拥有自定义错误处理函数(主要是为了更轻松的调试和错误输出,我厌倦了 PHP 在错误时输出的不必要的 HTML 标签),但保留不向用户记录这些自定义错误处理函数捕获的错误的选项,即使运算符“@”用于某些表达式。

下面是更详细的问题示例:

function custom_error_handler($errno, $errstr, $errfile, $errline) {
    $res = [
        'error_number' => $errno,
        'error_severity' => ERROR_LEVELS[$errno], // custom constant to get textual severity of the error (not important)
        'error_message' => $errstr,
        'error_file' => $errfile,
        'error_line' => $errline
    ];

    // logging to file with UID...

    if(DEBUG) { // if debugging is on (false for production)
        http_response_code(500);
        print_r(json_encode($res));
    }
    else {
        http_response_code(500);
        print_r(json_encode(['error_uid' => $log_uid]));
        exit;
    }
}

set_error_handler('custom_error_handler');

echo $x;
// unset/unknown variable - should print out error and continue with execution since it is a notice (or warning I'm not sure)
$guid = @$_GET['guid']
// should not print error if '$_GET['guid']' is not set/is empty

在此设置中,两个错误都会被记录下来!

提前致谢!

PHP 错误处理

评论

0赞 symcbean 9/27/2023
这听起来像是 XY 问题。首先,我从来没有遇到过PHP错误不是编程错误导致的实例。这两个示例实例是 bug。其次,即使关闭了 error_reporting / @,错误也会对性能产生重大影响。即它们需要被记录和修复。是的,将错误转储到浏览器是不好的。“基本上,它将错误报告设置为 0” - 不,它禁止错误 - 请参阅 php.net/manual/en/language.operators.errorcontrol.php 并显式调用任何自定义错误处理程序。
0赞 symcbean 9/27/2023
我投票结束这个问题,因为这正是系统的指定行为
0赞 BakirG 9/27/2023
是的,当然@symcbean,自定义错误处理函数可以捕获所有错误,这是它在 PHP 中的工作方式,我已经阅读了手册......但是,如果你理解了我的问题,我的目标是询问是否有任何可能的解决方法。为了你,我将大大简化我的问题:“除了带有 HTML 标签的默认文本之外,有没有办法以更好的格式获取 PHP 错误和异常。最好是 JSON 格式,其中包含调试所需的所有数据。请记住,我痴迷于@,并想永远使用它”。这足够澄清吗?
0赞 shingo 9/27/2023
你只需要关闭display_errors。
0赞 BakirG 9/27/2023
我需要显示所有错误。nvmnd 我发布了对我有用的答案

答:

-1赞 BakirG 9/27/2023 #1

执行此操作

if (error_reporting() != E_ALL) {   
    return false;
}

所以整个函数看起来像

function custom_error_handler($errno, $errstr, $errfile, $errline) {
    $res = [
        'error_number' => $errno,
        'error_severity' => ERROR_LEVELS[$errno],
        'error_message' => $errstr,
        'error_file' => $errfile,
        'error_line' => $errline
    ];

    // logging to file with UID...

    // if suppressed error
    if (error_reporting() != E_ALL) {
        return false;
    }
        
    if(DEBUG) {
        http_response_code(500);
        print_r(json_encode($res));
    }
    else {
        http_response_code(500);
        print_r(json_encode(['error_uid' => $log_uid]));
        exit;
    }
}

set_error_handler('custom_error_handler');

echo $x;
// will print error
$guid = @$_GET['guid']
// wont print error

如果任何人都会自己阅读,他们会更好地学习和理解,所以:

检查这个问题和最新的答案(适用于 PHP > 8.0.0)

和本用户在文档上的通知