我可以尝试/发现警告吗?
我需要捕捉一些从本地函数抛出的警告,然后处理它们。
特别:
array dns_get_record ( string $hostname [, int $type= DNS_ANY [, array &$authns [, array &$addtl ]]] )
它会在DNS查询失败时引发警告。
try
/ catch
不起作用,因为警告不是一个例外。
我现在有两个select:
-
set_error_handler
看起来像是过度杀伤,因为我必须使用它来过滤页面中的每一个警告(这是真的吗? -
调整错误报告/显示,使这些警告不会回显到屏幕上,然后检查返回值; 如果为
false
,则不会为主机名findlogging。
这里最好的做法是什么?
设置和恢复error handling程序
一种可能是在调用之前设置自己的error handling程序,稍后用restore_error_handler()
恢复以前的error handling程序。
set_error_handler(function() { /* ignore errors */ }); dns_get_record(); restore_error_handler();
你可以build立这个想法,并编写一个可重用的error handling程序,为您logging错误。
set_error_handler([$logger, 'onSilencedError']); dns_get_record(); restore_error_handler();
将错误转化为例外
你可以使用set_error_handler()
和ErrorException
类将所有的php错误转化为exception。
set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) { // 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 handling程序时要注意的一点是,它将绕过error_reporting
设置并将所有错误(通知,警告等)传递给error handling程序。 您可以在set_error_handler()
上设置第二个参数来定义您想要接收的错误types,或者在error handling程序中使用... = error_reporting()
来访问当前的设置。
禁止警告
另一种可能是用@运算符来抑制调用,然后检查dns_get_record()
的返回值。 但我build议不要这样做,因为错误/警告触发处理,不被压制。
真正起作用的解决scheme竟然是用E_WARNING
参数设置简单的error handling程序,如下所示:
set_error_handler("warning_handler", E_WARNING); dns_get_record(...) restore_error_handler(); function warning_handler($errno, $errstr) { // do something }
要小心@
操作符 – 而它禁止警告,它也可以抑制致命的错误。 我花了很多时间在有人写过@mysql_query( '...' )
的系统中debugging一个问题,问题是没有将mysql支持加载到PHP中,并且抛出了一个沉默的致命错误。 对于那些属于PHP核心的东西是安全的,但请小心使用它。
bob@mypc:~$ php -a Interactive shell php > echo @something(); // this will just silently die...
没有更多的输出 – 祝你好运debugging!
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:~$
这一次,我们可以看到为什么失败。
我想尝试/捕捉一个警告,但同时保持通常的警告/错误logging(例如在/var/log/apache2/error.log
); 为此处理程序必须返回false
。 然而,由于“throw new …”语句基本上中断了执行,因此必须执行“wrap in function”技巧,这也在下面讨论:
有没有一种静态的方式来抛出exception在PHP中
或者简而言之:
function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) { return false && throwErrorException($errstr, 0, $errno, $errfile, $errline); # error_log("AAA"); # will never run after throw /* Do execute PHP internal error handler */ # return false; # will never run after throw } ... set_error_handler('warning_handler', E_WARNING); ... try { mkdir($path, 0777, true); } catch (Exception $e) { echo $e->getMessage(); // ... }
编辑:仔细检查后,事实certificate它不工作:“ return false && throwErrorException ...
”将基本上, 不抛出exception,只是login错误日志; 删除“ false &&
”部分,如“ return throwErrorException ...
”,将使exception投掷的工作,但将不会loginerror_log …我仍然保持这张贴,虽然,因为我没有'看不到其他地方logging的这种行为
你也许应该试着完全摆脱这个警告,但如果这是不可能的,你可以用@(即@dns_get_record(…))预先拨打电话,然后使用任何可以得到的信息来判断是否发生警告或不。
通常你不应该使用@除非这是唯一的解决scheme。 在这种情况下,函数dns_check_record应该先用来知道logging是否存在。
如果dns_get_record()
失败,它应该返回FALSE
,所以你可以用@
来抑制警告,然后检查返回值。
尝试检查它是否返回一些布尔值,然后你可以简单地把它作为一个条件。 我遇到了oci_execute(…),这是返回一些违反我唯一的关键。
ex. oci_parse($res, "[oracle pl/sql]"); if(oci_execute){ ...do something }
我只会推荐使用@来压制警告,例如$ prop = @($ high /($ width – $ depth));跳过除零警告。 但在大多数情况下,最好处理。