我需要捕捉一些警告从一些php本机函数抛出,然后处理它们。

具体地说:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

当DNS查询失败时,它抛出一个警告。

Try /catch不起作用,因为警告不是异常。

我现在有两个选择:

set_error_handler似乎是多余的,因为我必须使用它来过滤页面中的每个警告(这是真的吗?); 调整错误报告/显示,这样这些警告就不会显示在屏幕上,然后检查返回值;如果为假,则没有找到主机名的记录。

这里的最佳实践是什么?


当前回答

小心使用@操作符——虽然它抑制了警告,但也抑制了致命错误。我花了很多时间调试系统中的一个问题,其中有人写了@mysql_query('…’),问题是mysql支持没有加载到PHP中,它抛出了一个无声的致命错误。它对于PHP核心的一部分是安全的,但请谨慎使用。

bob@mypc:~$ php -a
Interactive shell

php > echo @something(); // this will just silently die...

没有进一步的输出-祝你调试好运!

bob@mypc:~$ php -a
Interactive shell

php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error:  Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
bob@mypc:~$ 

这次我们可以看到为什么它失败了。

其他回答

我只建议在直接操作时使用@来抑制警告(例如$prop = @($high/($width - $depth));跳过0警告的除法)。然而,在大多数情况下,这是更好的处理。

小心使用@操作符——虽然它抑制了警告,但也抑制了致命错误。我花了很多时间调试系统中的一个问题,其中有人写了@mysql_query('…’),问题是mysql支持没有加载到PHP中,它抛出了一个无声的致命错误。它对于PHP核心的一部分是安全的,但请谨慎使用。

bob@mypc:~$ php -a
Interactive shell

php > echo @something(); // this will just silently die...

没有进一步的输出-祝你调试好运!

bob@mypc:~$ php -a
Interactive shell

php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error:  Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
bob@mypc:~$ 

这次我们可以看到为什么它失败了。

尝试检查它是否返回一些布尔值,然后你可以简单地把它作为一个条件。我遇到这与oci_execute(…)返回一些违反我的唯一键。

ex.
oci_parse($res, "[oracle pl/sql]");
if(oci_execute){
...do something
}

从PHP7开始,你可以像这样捕捉大多数错误和警告:

try {
    whatever();
} catch (Throwable $e) {
}

更多:https://www.php.net/manual/en/language.errors.php7.php

设置和恢复错误处理程序

一种可能是在调用之前设置自己的错误处理程序,然后使用restore_error_handler()恢复之前的错误处理程序。

set_error_handler(function() { /* ignore errors */ });
dns_get_record();
restore_error_handler();

您可以在此基础上编写一个可重用的错误处理程序,为您记录错误。

set_error_handler([$logger, 'onSilencedError']);
dns_get_record();
restore_error_handler();

将错误转化为异常

您可以使用set_error_handler()和ErrorException类将所有php错误转换为异常。

set_error_handler(function($errno, $errstr, $errfile, $errline) {
    // error was suppressed with the @-operator
    if (0 === error_reporting()) {
        return false;
    }
    
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    dns_get_record();
} catch (ErrorException $e) {
    // ...
}

在使用您自己的错误处理程序时需要注意的重要一点是,它将绕过error_reporting设置并将所有错误(通知、警告等)传递给您的错误处理程序。您可以在set_error_handler()上设置第二个参数来定义您希望接收的错误类型,或者使用…错误处理程序中的= error_reporting()。

抑制警告

另一种可能是使用@操作符抑制调用,然后检查dns_get_record()的返回值。但我建议不要这样做,因为错误/警告是被触发来处理的,而不是被抑制的。