PHP异常真的比错误更有用吗? (进阶)

时间:2009-10-26 17:26:08

标签: php exception-handling error-handling

我相信在正确编码的系统中 - 错误(作为错误或异常)不应该是可能的(除了DB / memcached服务器关闭导致查询失败)。我们的代码不应该依赖任何假设才能正常工作,并且应该尽可能地作为防弹。

但是,为了确保我们的系统以最友好的方式处理问题,我们必须构建并实施某种“捕获系统”,以确保如果出现任何问题,我们的服务器工作人员和最终用户将得到照顾。

为此,PHP提供了两种解决方案 - 错误和异常。错误由5个值组成,而异常由包含在对象中的5个值组成。两者都允许在构建应用程序时非常有用的回溯。

  

5个值是$ error_code,   $ error_message,$ file,$ line,$ context

通常,在我们努力进行适当的OOP编程时,默认选择始终是追求对象 - 但在这种情况下,我不确定它们实际上是多么有益。通过使用异常,浪费了额外的内存以满足在对象中包装值的需要(这通常还需要包含异常类的额外文件)。此外,您必须在TRY / CATCH {}块中包装您认为可能失败的任何代码。这使得错误处理方法对人为错误开放,因为开发人员可能无法解决故障点。为了安全防范这种情况,您可以使用set_exception_handler,它将传递任何未捕获的异常。关于异常处理程序的坏处是执行将在调用exception_handler之后停止 - 因此如果没有在try / catch块中捕获,则不存在可恢复/忽略的异常。

另一方面,错误总是全局的,可以由set_error_handler设置的任何函数/类处理。这消除了对额外异常类,对象内存或try / catch代码行的需要。与异常一样,错误也伴随着构建错误代码(与异常不同),您可以使用它来继续脚本执行,以解决轻微或不重要的脚本问题。此外,大多数PHP函数都会触发错误,因此您不会违反语言流程。

因此,无论如何你必须支持错误处理(对PHP语言做),浪费额外代码和内存以及实现异常的目的是什么?我们只是盲目地这样做是因为它是对象形式的错误,还是应用程序设计中有一个真正的好处,正常的错误是我们无法承受的?

4 个答案:

答案 0 :(得分:8)

我在这一行后停止阅读:

  

我相信正确编码   系统 - 错误(如错误或错误)   例外)不应该是可能的   (DB / memcached除外   服务器关闭导致查询   失败)。

这是例外的完整目的 - 作为在代码中管理特殊情况的构造。

如果您将异常作为 un 特殊普通程序流程的一部分抛出,那么您做错了。

如果您不知道为什么例外对特殊情况有用,那么您可能需要花一些时间使用真正的OO语言。 (提示:PHP不是真正的OO语言。)

答案 1 :(得分:4)

除了所有这些错误的面向对象方法外,还有扩展异常的巨大优势。

因此,您可以捕获一个catch块(FileNotFoundException,FileNotWritableException,...)中的IOExceptions的所有子异常,以及另一个异常中的所有其他异常,您可能会再次抛出该异常:< / p>

try
{
    // [...] (some code causing the exception)
}
catch(IOException $e)
{
    // do your processing here, like let's say set correct filemodes.
}
catch(Exception $e)
{
    // catches all other exceptions
}

它们还为您提供了一种更标准化的方式来处理脚本中的错误。当你使用try / catch块时,错误处理几乎总是看起来类似,并且在许多情况下比使用代码等的正常错误更加不言自明。

你能更好地理解哪一个:?

switch($errorCode)
{
    case 1450:
        // Create the database column
        break;
}

// or

catch(ColumnNotFoundException $e)
{
    // Create the database column
}

答案 2 :(得分:4)

我认为错误例外的定义之间存在哲学上的差异。

错误简单地说是一个编程的缺陷,由代码中的逻辑谬误生成。传递strlen()不正确数量的参数自然应该是一个错误。另一方面,异常处理所有内容都正确编程的情况,但您的代码与代码库之外的资源(文件系统,Web服务,外部可执行文件等)进行交互。虽然预计这样的外部资源应该在每次调用时都能正常工作,但是有些情况 - 超出程序控制范围 - 不会归因于代码的错误(文件系统被卸载,连接超时等) 。由于这些问题是由于外部因素造成的,因此被视为例外。

主要区别在于,在一个人自己的代码中发生错误,而在第三方资源中发现异常的情况下会发生异常。

答案 3 :(得分:0)

fopen()函数可以返回以下内容:

  

如果打开失败,则出现级别错误   生成 E_WARNING 。你可以用@   抑制这个警告。

您可以选择使用抑制运算符,但它本身会产生相当大的开销。 try / catch块使您能够捕获此错误,继续定期执行,向用户显示自定义错误,并一次性记录错误。对我而言,在我的文档中使用异常处理的好处并不明白。

此外,如果您使用任何Zend Framework(包括任何Google API类),您应该按照自己的方式自行处理异常。