与我的团队争吵之后,因为我们对这种情况都有不同的看法。什么时候关闭PHP错误消息,或者抑制某些抛出警告的功能,通知无论出于什么原因。
我理解每个人都说你应该在生产环境中关闭error_reporting,但这可能会导致一些不会被拾取的并发症。所以没有什么能得到修复。 PHP提供了许多不同的方法来控制错误消息。例如:
$Var = "Variable Is Set";
if (@$Var){ echo $Var; }
结束:
if (isset($Var)){ echo $Var; }
因为我们有一个set变量,所以这将成功回显..如果我们没有set变量,那么会抛出一个通知..那么使用哪一个?是设置还是错误抑制?
在生产环境中,哪一个更容易被使用?
error_reporting(0);
以上内容将关闭所有类型的PHP错误报告,即使遇到问题也不会显示任何错误消息。因此,在某些情况下,由于消息被破坏,这可能会导致代码因为未知原因而停止工作
或:
set_error_handler("");
上面启用了一个自定义错误处理程序,可以用来向用户优雅地显示错误,并使管理员能够记录详细的警告..但是,再一次,我知道的error_handler在致命时不会被调用错误被触发?
那么我的整体问题是什么?
处理生产环境中的错误或者只是将其关闭?这可以归结为我认为的最佳实践和偏好。但是这让我和我的团队感到困惑到了分歧的地步。
答案 0 :(得分:5)
您从不完全关闭错误报告。您执行关闭错误显示。在开发过程中必须直接将错误转储到屏幕上(除非你有其他方法可以解决所有错误),在生产中你需要相同的错误报告,而不是输出可见的错误,你想要它只记录它们。这可以使用PHP的错误报告配置设置完成。
如果您需要特殊的自定义错误处理/日志记录,请使用自定义错误处理程序。
对于@
,您永远不会以某种方式编写应用程序,因为它会对您依赖的行为产生实际错误。您以不会触发错误的方式编写所有内容。只有在无法避免可能的错误时才使用@
,因为您无法以任何其他方式编写它,并且期望出错并且正在处理它;然后你所做的就是压制不可避免的错误信息。
答案 1 :(得分:3)
对不起,这不是一个明确的解决方案,但经过几年的反复试验,我提出了以下做法,这些做法都是我自己的,并且运作良好:
1 - 切勿使用@来抑制错误。切勿使用任何东西盲目隐藏或忽略所有错误。所有错误都很重要,不应忽略任何错误。
2 - 按照RafaSashi的建议,打开错误记录并关闭显示错误。
3 - 在PHP.INI中使用error_reporting = 2147483647
激活所有错误报告。这将使PHP非常挑剔您可能做错的任何事情,帮助您了解更多信息并及时了解未来的语言弃用和更改。
4 - 您还可以创建自己的错误记录,以您想要的方式准确记录您想要的内容。查看error_log()
的手册。如果您使用它,您甚至可以关闭,并开始手动记录,这将使您完全控制PHP的错误记录系统。
5 - 我在所有PHP代码中都使用OOP,所以我到处都使用异常,我建议大家都这样做。他们在简单的错误处理之前就已经光明了几年。使用此代码拦截代码中的所有错误并将其作为例外抛出:
set_error_handler('ErrorHandler');
function ErrorHandler($Code, $Message)
{
throw new Exception($Message, $Code);
}
6 - 没有向用户显示任何错误是没有意义的。应该显示一些错误,一些应该隐藏,一些应该显示为一般问题(不要告诉用户确切的问题)。
a)应显示的错误:由用户引起的所有内容,例如无效的表单输入或错误的行为。这很明显,但应该提到。
b)应隐藏的错误:仅隐藏代码可以处理和纠正的错误。例如,您可以进行数据库连接,如果失败,您可以再试一次。如果第二次尝试成功,继续,没有人应该知道第一次尝试失败。如果需要,只需使用error_log()
进行记录即可。有时,变量尚不存在,因此请使用isset()
进行检查,并在需要时对其进行初始化。无需将此报告为错误。
c)应显示为通用的错误:大多数错误都属于此类别。您不会向用户显示PHP内存耗尽,或SMTP服务器脱机或数据库连接被拒绝等内容。只需学习如何使用try
包装危险代码,使用catch捕获任何错误,并将消息转换为可以向用户显示的内容。例如:
try
{
// Dangerous code ahead: we will try to connect to the database, but it
// can be offline.
$mysqli = new mysqli("localhost", "user", "password", "database");
}
catch(Exception $e)
{
// If we're here, something bad happened during connection. Let's handle it.
// Notify staff, log error, do anything you can to get someone to quickly
// check the issue.
SendMailAdmin("Database connection Error, check ASAP.");
error_log("Database connection Error, check ASAP.");
// And show the user some message. You don't need to tell him about any
// detail regarding what truly caused the error.
die("A problem occurred in our servers. Our technical staff has been notified,
please try again in a few minutes.");
}
// If we're here, everything worked fine, so do your DB query and so on....
而不是die()
,您可以使用您认为合适的内容:重新抛出另一个例外,将标头重定向到一般错误消息或任何您想要的内容。
7 - 这是更高级的,但您也可以这样做:创建自己的异常层次结构,如下所示:
class MVXException extends Exception {}
class ExMVXDB extends MVXException {}
class ExMVXDBRead extends ExMVXDB { }
class ExMVXDBWrite extends ExMVXDB { }
class ExMVXDBNotFound extends ExMVXDB { }
这是我在自制框架中的异常树的简化。这样做的好处是,如果您执行catch(ExMVXDB $e)
,您将捕获所有数据库错误。但是,如果您只想捕获数据写入操作,则可以执行catch(ExMVXDBWrite $e)
。
那就是它。错误处理并不简单,并且没有直接的答案,但有很多工具和良好实践可以帮助您选择最适合您的方法。
答案 2 :(得分:1)
1 - 您可以关闭display_errors并打开log_errors
@ini_set('log_errors','On');
@ini_set('display_errors','Off');
2 - 你可以使用默认的php Error和Logging功能&常数
请参阅:http://www.w3schools.com/php/php_ref_error.asp
3 - 您可以使用PHP Filesystem
实现自己的一组错误和日志记录功能