为避免出错时抓破额头,你必须了解的PHP错误内容
纯粹的面向对象的语言主要产生异常来提示错误,而PHP一开始就是程序化的,所以它有各种各样的错误,可以和 异常一起被提出。
错误是人类的,但我们必须识别它们
没有一个活着的程序员在他们职业生涯的某个阶段在编码时不犯错误。这只是过程的一部分,重要的是要认识到,我们都会不时地犯这些类型的错误。也就是说,最好是在错误发生时发现它们,以便在此时纠正它们。
一个人对自己所犯的 错误反应得越快,他们就越能纠正这些相同的错误,并在他们所做的编程中真正有所作为。换句话说,可能有必要迅速采取行动来纠正错误,这样项目本身就不会被打乱。
当你发现错误时,你将如何前进,这完全取决于你,但最好的办法是提醒自己,这是预料之中的,你可以做一些事情来纠正它。
这两者之间的区别是什么?
异常是可以用try/catch块来管理和捕获的对象。你可以创建你自己的 异常类,带有自定义参数和方法。它们确实是具有特殊附加功能的对象,在PHP 5和更高版本中,你肯定应该用它们来管理你的错误。
错误像异常一样伴随着一条消息,但它们是通过调用一个错误处理函数(可能是自定义的)来管理的,当它们发生时。PHP和它的本地函数主要产生错误而不是异常。PDO和SPL是个例外(真是双关语),因为它们有一个面向对象的Api,也能理解异常类。
异常总是冒泡,直到它们被捕获;而错误则被传递给当前的错误处理程序,其工作是决定如何处理它们。对于非严重的错误,用粗体打印并继续执行是默认行为。
理解异常及其用法是向面向对象的PHP过渡的一个关键话题,但不在本文的讨论范围内。在这里我们将对待错误,因为你总是要和PHP本地函数打交道,即使你的代码非常好,只向你的自定义层次结构抛出异常:当你省略了{,会产生一个错误,而不是一个异常。当传递给include()的文件丢失时,同样会产生一个错误,而不是一个异常。
大多数情况下,未处理的错误是编程错误的结果:如果你得到一个错误的生成,可能已经有了真正的错误,你不应该忽视它们。
翻译成异常
然而,以面向对象的方式处理错误是非常困难的:你不能捕捉它们。因此, PHPUnit通过定义一个自定义的错误处理程序将错误转化为异常,在可控错误的情况下抛出PHPUnit_Frameworks_Error_Notice或PHPUnit_Framework_Error_Warning。
如果出现错误,PHPUnit也会在测试基础中用E来提示你,而F是为指定断言失败的特殊异常保留的。
没有什么能阻止你做同样的事情:通过定义你的错误处理程序,你可以将include()中丢失文件的错误转化为你可以捕获的异常。问题是:你应该吗?通常情况下,一个缺失的文件,当包含例如一个类的源代码时,只会导致一个更严重的错误,如Fatl,当脚本被允许继续时。
主要的错误类型
这些是主要的错误类型,在 PHP 4 之前的语言中都有。在开发过程中,大部分时间只会看到这四种错误类型中的一种:
-
E_NOTICE:一个非关键性的错误,如访问一个初始化变量。PHP是非常宽容的,在生产环境中会允许脚本继续运行。
-
E_WARNING:一个更严重的错误,比如向 foreach()传递一个非遍历变量,或者包括一个缺失的文件。
-
E_PARSE:一个语法错误,比如缺少一个}或者使用一个保留的关键字来命名一个类。脚本根本就不会运行,因为这些错误是在编译(到p代码)时提出的。
-
E_ERROR:也被称为致命错误,它们是无法恢复的,即使是错误处理程序。在null上调用一个方法,或者调用一个未定义的函数,或者创建一个不存在的类的对象,都会导致Fatal Error,这将突然终止脚本(即使它是一个测试套件!)。
还有许多其他类型的错误,但比较少遇到。完整的列表在PHP手册中。
从这个列表中,应该提到一些有趣的特殊错误。
- E_STRICT:违反了严格的标准,从 PHP 5.3 开始,它就在默认情况下。如果你静态地调用一个非静态方法(通过Class::method()),你会得到这个错误。启用严格标准可以帮助你提高代码质量。
E_RECOVERABLE_ERROR:致命错误的可捕捉版本,例如试图将一个没有__toString()的对象转换成一个字符串。它可以由错误处理程序管理,而Fatal Error和Parse Errors则不能(它们使解释器处于不稳定状态并导致立即退出())。
php.ini指令
有两个指令对于管理错误非常有趣。
第一个是error_reporting,它规定了报告某些类型的错误,同时掩盖其他的。一般来说,这个值在生产环境(不向最终用户显示任何东西,因为它不会理解)和开发环境(向我显示一切,因为我想在发货前消除所有错误。)
事实上,在开发中,我总是将错误报告设置为E_ALL。其他的都是90年代的东西。
display_errors也必须设置为On,才能打印错误。当你得到一个空白页而不是预期的结果时,请检查这个指令。
PHP函数
error_reporting()允许你设置报告哪些错误,并覆盖php.ini中的error_reporting,同样通过使用E_ALL和其他常数。注意,有些错误,如E_PARSE,是在编译时检测到的,所以不会受到这个函数的影响。
set_error_handler()允许你定义自己的函数来管理错误,然后可以委托给PHP默认的处理程序或完全覆盖它。
归纳要点
错误是PHP中一个棘手的部分,但知道如何阅读它们会加速你的开发。在你的代码中,总是定义异常,它的用途更广,但要准备好管理由PHP本身抛出的错误。
大多数时候,它们只是编程错误,如变量名称中的一个错别字或缺少一个分号。然而,你应该知道如何定义自定义错误处理程序,以备被迫处理运行时的错误,如套接字或数据库连接的问题。