在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_errors
closures(您的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 denied
, save mode restriction
, open_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刮刀。