【问题标题】:Are there any "gotchas" with this approach to handling errors in PHP?这种处理 PHP 错误的方法有什么“陷阱”吗?
【发布时间】:2010-11-28 12:50:35
【问题描述】:

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

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

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

我认为这很好地涵盖了大多数情况,但正如我所说,我对 PHP 很陌生,所以我不知道是否有我忽略的极端情况或奇怪的行为。

我的计划有什么缺陷?我该如何克服它们?

【问题讨论】:

  • 这是一个可靠的方法,是的。

标签: php exception exception-handling error-handling


【解决方案1】:

总体而言,让意外异常冒泡到顶部 catch 块然后提供 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
}

而不是这个:

try {
    $result = php_function($argument);
}
catch (Exception $ex) {
    // error handling here
}

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

更新:

我并不是说您应该使用@ 来忽略来自函数调用的错误。我要说的是,当使用以这种方式运行的遗留 PHP 函数时,并且当您完全准备好处理错误并从中恢复时,那么当然不应再将其视为关于您的应用程序执行的“错误”。 在这种特定情况下,我建议将其隐藏,以免也被报告。

【讨论】:

  • 你的@php_function($argument);太可怕了。 @在这里无关。而且你在这里用错误报告搞乱了错误处理。虽然情况不同。 无论如何处理,都应始终报告错误。
  • 除了“我不喜欢它”还有什么论据?
  • 所以,a) 无论如何我都无法捕获 E_ERROR;它只会杀死我的应用程序并且将无法处理(这些东西是应该在 prod 之前捕获的语法错误,还是它们有时会意外出现?),以及 b)我是否应该将所有内容都包装在一个异常中如果我想使用@ 抑制,自定义错误处理函数?一般来说,编写自定义错误处理程序的“好”方法是什么?
  • 请允许我不同意。 @一切在这里做。它表示您期待一个错误,并且您不希望它被报告,因为您准备在它发生时处理它。您是否曾经需要使用 getimagesize 之类的函数编写生产代码?
  • 有什么方法可以向自定义处理程序表明您抑制了错误,还是 PHP 只是调用您的处理程序并让后果自负?
猜你喜欢
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
相关资源
最近更新 更多