在PHP中用@操作符来抑制错误

在你看来,使用@操作符来抑制PHP中的错误/警告是有效的,而你可能正在处理错误?

如果是这样,你会在什么情况下使用这个?

代码示例是受欢迎的。

编辑:注意到repliers。 我不打算closures错误报告,但是,例如,通常的做法是使用

@fopen($file); 

然后再检查…但是你可以通过这样做来清除@

 if (file_exists($file)) { fopen($file); } else { die('File not found'); } 

或类似的。

我想这个问题是 – 有什么地方可以用来抑制一个错误,不能以任何其他方式处理?

我会压制这个错误并处理它 。 否则,您可能会遇到TOCTOU问题(检查时间,使用时间,例如,在file_exists返回true之后,但在fopen之前,文件可能会被删除)。

但是,我不会只是压制错误,让他们消失。 这些更好地可见。

注意:首先,我意识到99%的PHP开发人员使用了错误抑制运算符(我曾经是其中之一),所以我期望任何看到这个的PHP开发人员都不会同意。

在你看来,使用@操作符来抑制PHP中的错误/警告是有效的,而你可能正在处理错误?

简短的回答:
没有!

再更正确的答案:
我不知道,因为我什么都不知道,但到目前为止,我还没有遇到过这样一个好的解决scheme。

为什么这么糟糕:
在我现在使用PHP大约7年的时间里,我已经看到了由错误抑制操作引起的无尽的debugging痛苦,从来没有遇到过这种情况是不可避免的。

问题是你压制错误的那段代码目前可能只会导致你所看到的错误; 但是,当您更改被压缩线依赖的代码或其运行环境时,该线将尝试输出与您要忽略的错误完全不同的错误。 那么你如何追踪一个不输出的错误呢? 欢迎来到debugging地狱!

我花了好多年的时间才意识到,由于被压制的错误,我每隔几个月就浪费了多less时间。 大多数情况下(但不是完全),这是在开发者环境中安装了第三方脚本/应用程序库/库,它没有错误,但不是我的,因为php或服务器configuration不同或缺less依赖关系,通常会立即输出错误提醒问题是什么,但不是当开发者添加魔术@时。

替代品(取决于情况和期望的结果):
处理你所知道的实际错误,这样,如果一段代码将导致一定的错误,那么它不会在特定的情况下运行。 但是我认为你会得到这个部分,你只是担心最终用户会看到错误,这就是我现在要解决的问题。

对于常规错误,您可以设置一个error handling程序,以便在您查看页面时以您希望的方式输出error handling程序,但对最终用户隐藏并logging下来,以便您知道用户触发了哪些错误。

对于致命的错误设置display_errorsclosures(您的error handling程序仍然被触发)在您的php.ini和启用错误logging。 如果你有一个开发服务器和一个活的服务器(我build议),那么你的开发服务器上不需要这个步骤,所以你仍然可以debugging这些致命的错误,而不必诉诸于错误日志文件。 使用shutdown函数甚至有一个把大量的致命错误发送到你的error handling程序的技巧 。

综上所述:
请避免它。 可能有一个很好的理由,但我还没有看到一个,所以直到那一天,我认为(@)错误抑制运算符是邪恶的。

如果你想要更多的信息,你可以在PHP手册的Error Control Operators页面上阅读我的评论 。

是的抑制是有道理的。

例如,如果文件无法打开, fopen()命令返回FALSE 。 这很好,但它也会产生一个PHP警告消息。 通常你不需要警告 – 你会自己检查FALSE

事实上,在这种情况下, PHP手册特别build议使用@

如果在使用fopen()之类的函数时不想引发警告,则可以禁止该错误,但使用exception:

 try { if (($fp = @fopen($filename, "r")) == false) { throw new Exception; } else { do_file_stuff(); } } catch (Exception $e) { handle_exception(); } 

除非你知道你可以处理所有的条件,否则应该避免错误抑制。

这可能比首先看起来要困难得多。

你真正应该做的是依靠php的“error_log”作为你的报告方法,因为你不能依靠用户查看页面来报告错误。 (你也应该禁用PHP来显示这些错误)

那么至less你会得到一个全面的报告,说明系统中出现的所有问题。

如果你真的必须处理错误,你可以创build一个自定义error handling程序

http://php.net/set-error-handler

那么你可能会发送exception(可以处理),并做任何需要向pipe理部门报告奇怪的错误。

我永远不要让自己使用“@”…句点。

当我在代码中发现“@”的用法时,我添加了一些注释,使它们在使用点和使用它的函数的docblock中显而易见。 由于这种错误抑制,我也被“追鬼”debugging咬了,我希望通过强调它的使用来让下一个人更容易。

如果我想自己的代码抛出一个exception,如果一个本地的PHP函数遇到一个错误,'@'似乎是一个简单的方法去,我反而select做别的,得到相同的结果,但是(再次)在代码中显而易见:

 $orig = error_reporting(); // capture original error level error_reporting(0); // suppress all errors $result = native_func(); // native_func() is expected to return FALSE when it errors error_reporting($orig); // restore error reporting to its original level if (false === $result) { throw new Exception('native_func() failed'); } 

这是更多的代码,只是写:

 $result = @native_func(); 

但为了追随我的那个可怜的debugging灵魂,我宁愿让我的压制需要很明显。

大多数人不明白错误信息的含义。
没有开玩笑 他们中的大多数。

他们认为错误信息都是一样的,说:“出了点问题!”
他们懒得读它。
虽然这是错误信息中最重要的部分 – 不仅仅是提出的事实,而是它的意义。 它可以告诉你什么是错的。 错误消息是为了帮助,而不是用“如何隐藏它”来打扰你。 问题。 这是新手networking编程界最大的误解之一。

因此,而不是堵塞错误消息,人们应该阅读它说什么。 它不仅有一个“找不到文件”的值。 可能有数千个不同的错误: permission deniedsave mode restrictionopen_basedir restriction等等。 每个人都需要适当的行动。 但是,如果你嘲笑它,你永远不会知道发生了什么!

OP正在搞错误报告和错误处理 ,而这是非常大的差异!
error handling是针对用户的。 这里“发生了什么事”就够了。
虽然错误报告是为程序员,谁迫切需要知道发生了什么事情。

因此,永远不要堵塞错误消息。 既为程序员logging,又为用户处理

有没有办法从php.ini警告和错误压制? 在这种情况下,你可以debugging只改变一个标志,而不是试图发现哪个@隐藏问题。

使用@有时会产生反效果。 根据我的经验,您应该始终在php.ini中打开错误报告或致电

 error_reporting(0); 

在生产现场。 通过这种方式,当您处于开发阶段时,您只需注释掉该行并保持错误可见即可进行debugging。

我真正需要使用它的唯一地方是评估函数。 eval的问题在于,当由于语法错误而无法parsingstring时,eval不会返回false,而是会抛出一个错误,就像在常规脚本中存在parsing错误一样。 为了检查存储在string中的脚本是否可parsing,可以使用如下所示的内容:

 $script_ok = @eval('return true; '.$script); 

AFAIK,这是最优雅的方式来做到这一点。

我使用它的一个地方是在套接字代码中,例如,如果你有一个超时设置,如果你不包含@,那么你将会得到一个警告,即使它没有得到一个数据包也是有效的。

 $data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port ) 

你不想压制一切,因为它减慢你的脚本。

是的,在php.ini和脚本中都有一种方法可以删除错误(但是只有在实时环境中执行此操作,并从php中logging错误)

 <?php error_reporting(0); ?> 

你可以阅读这个关于php.ini版本的closures。

如果您正在使用自定义error handling函数并想要抑制错误(可能是已知错误),请使用此方法。 在这个上下文中使用'@'不是一个好主意,因为如果设置了error handling程序它不会抑制错误。

写3个函数,像这样调用。

 # supress error for this statement supress_error_start(); $mail_sent = mail($EmailTo, $Subject, $message,$headers); supress_error_end(); #Don't forgot to call this to restore error. function supress_error_start(){ set_error_handler('nothing'); error_reporting(0); } function supress_error_end(){ set_error_handler('my_err_handler'); error_reporting('Set this to a value of your choice'); } function nothing(){ #Empty function } function my_err_handler('arguments will come here'){ //Your own error handling routines will come here } 

我试图加载一个HTML文件作为DOMDocument对象进行处理时使用它。 如果在HTML中有任何问题…并且哪个网站没有至less一个 … DOMDocument-> loadHTMLFile()会抛出一个错误,如果你不用@来压制它的话。 这是唯一的方法(也许有更好的)我已经成功地在PHP中创buildHTML刮刀。