这种处理PHP错误的方法是否存在"陷阱"?

Age*_*rum 5 php error-handling exception-handling exception

我是PHP的相对新手,但在我看来,PHP的错误处理有点像一个贫民窟,错误和警告穿插异常(并且不要让我开始die()).因此,我不确定如何最好地创建,解释和处理我的应用程序中的所有错误情况.

我的总体攻击计划大致如下:

  1. 将所有警告/错误转换为异常,set_error_handler()用于包装错误.
  2. 防守代码,抢先检查我预计会出错的事情.仅在我无法直接处理错误时才抛出异常.通常try/catch会在需要时使用块,以处理我自己不会抛出的异常.
  3. 将我的整个应用程序(即我index.php的入口点文件)包装在自己的应用程序中try/catch.如果失败了,我会抛出HTTP 500并显示一个合适的错误页面.据推测,这个页面将是一个预编译的文件而不是标题/正文/页脚包含的集合 - 这在很大程度上是因为我仍然可以覆盖像乱码模板文件这样的奇怪异常.我认为这就是为什么Google的500级错误页面与他们推出的其他内容有很大不同.
  4. 作为#2和#3的推论,因为我希望能够提前处理所有事情,如果我决定抛出我自己的异常,我也期望不会发现错误,而是让它一直冒出来我的顶级处理程序.这里的想法是,如果我发现它无法处理它,我可能没有能力在其他任何地方处理它.我正在考虑给这些错误他们自己的子类 - 也许CriticalErrorException- 可以直接在我的日志中识别/产生一封电子邮件,以便我可以快速查看.一般来说,我期望这些可能是开发中可能发生的事情,但应该通过生产来解决.
  5. 任何使其成为顶部的错误都会记录在数据库中,并将故障转移到日志文件中.如上所述,严重错误会触发电子邮件.如果报告故障转移到文件 - 即存在数据库错误 - 那么也会触发电子邮件.

我认为这很好地涵盖了大多数情况,但正如我所说,我对PHP非常新,所以我不知道是否存在我忽略的极端情况或奇怪的行为.

我的计划有哪些缺陷?我怎样才能克服它们?

Jon*_*Jon 1

总的来说,让意外异常冒泡到顶部catch块然后提供 a 的策略HTTP 500是好的(许多框架就是这样做的)。

我不太同意这样做CriticalErrorException——也许您现在不希望捕获某些内容,但您可能会在将来扩展错误处理(可能面对额外的应用程序要求)。只要扔掉自然的东西即可。Exception在大多数情况下,简单的就可以了。

关于 PHP 错误:您并不严格需要转换E_ERROR为异常(无论如何它都会终止您的应用程序,并且也会显示在错误日志中)。不过,您最好处理一下E_NOTICE,因为通知几乎总是意味着代码有问题。

最后,当谈论引发警告的 PHP 函数时,我会这样说:

// Assume that php_function() raises E_WARNING and returns FALSE on error
// WARNING: if you have defined a custom error handler, IT WILL STILL BE CALLED
//          even though the @ operator suppresses the error
$result = @php_function($argument); // suppress error
if (!$result) {
    // error handling here
}
Run Code Online (Sandbox Code Playgroud)

而不是这个:

try {
    $result = php_function($argument);
}
catch (Exception $ex) {
    // error handling here
}
Run Code Online (Sandbox Code Playgroud)

原因是,当您打算立即对错误做出反应时,转换为异常并不会真正给您带来任何好处。相反,第一个代码片段将“告诉”阅读它的开发人员查找文档,了解php_function是否需要有关其错误处理策略的更多信息。第二个代码片段将要求开发人员了解应用程序中具体实现的错误处理的知识。

更新:

我并不是说您应该@忽略函数调用产生的错误。我的意思是,当使用以这种方式运行的旧版 PHP 函数时,并且当您完全准备好处理错误并从中恢复时,那么它当然不应再被视为关于应用程序执行的“错误”。在这种特定情况下,我建议抑制它,这样它就不会被报告。