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

具体地说:

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

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

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

我现在有两个选择:

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

这里的最佳实践是什么?


当前回答

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

其他回答

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

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

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

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

从PHP8开始,您可以执行以下操作,而不是设置错误处理程序来捕获错误和警告。我相信PHP 7。你可以捕捉一些错误。

try {
    call_user_func('sprintf', array_merge([$string], $args));
} catch (Throwable $e) {
    $logger->info('mesage...');
}

如果以这种方式隔离,您通常应该在可以传递或访问记录器的地方,因为它可以混淆编码器错误,例如将错误输入的参数传递给方法,并掩盖各种其他问题。

https://php.watch/versions/8.0/internal-function-exceptions

不确定是否注意到(可能没有),但您可以通过更多地考虑您想要做的事情来解决像这样的例子。

构建器模式和选项模式都为此提供了解决方案,在调用之前(可以是私有函数,也可以是有效性检查之后),您可以抛出一个真正的自定义异常,该异常仅可归因于您的代码。这将使内置函数使用起来非常安全。

另一个很好的做法是使用debug_backtrace和DEBUG_BACKTRACE_IGNORE_ARGS,或者在Throwable对象上使用getTrace或getTraceAsString方法,这样可以保留一些上下文。

通常你不应该使用@,除非这是唯一的解决方案。在这种情况下,应该首先使用dns_check_record函数来了解该记录是否存在。

小心使用@操作符——虽然它抑制了警告,但也抑制了致命错误。我花了很多时间调试系统中的一个问题,其中有人写了@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:~$ 

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