可悲的是,不管我们在写代码时多么小心,错误始终是有的。PHP将会为许多常见的我文件和运行问题提供错误,警告和一些通知,同时让我们知道如何检测和处理这些错误,使得调试程序容易的多。
PHP报告错误以响应许多内部错误条件。这些信号可用于表示许多不同的条件,并可根据需要显示和/或记录。PHP生成的每个错误都包含一个类型。我们提供了这些类型的列表,以及对它们的行为和如何导致它们的简短描述。
用PHP处理错误
如果未设置错误处理程序,则PHP将根据其配置处理发生的任何错误。报告和忽略哪些错误由配置文件php.ini中的error_reporting指令控制,或者在运行时通过调用error_reporting()
来控制。但是,强烈建议设置配置指令,因为在脚本开始执行之前可能会发生一些错误。
在开发环境中,您应该始终将error_reporting设置为E_ALL,因为您需要了解并修复PHP引发的问题。在生产中,您可能希望将其设置为不太冗长的级别,例如E_ALL
&~E_NOTICE
&~E_STRICT
&~E_DEPRECATED
,但在许多情况下,E_ALL也是适当的,因为它可能提供潜在问题的早期警告。
PHP如何处理这些错误取决于另外两个PHP.ini指令。display_errors控制是否将错误显示为脚本输出的一部分。在生产环境中,应该始终禁用此选项,因为它可以包含机密信息,如数据库密码,但在开发过程中通常对启用此选项很有用,因为它可以确保立即报告问题。
除了显示错误之外,PHP还可以在启用log_errors.指令时记录错误。这会将任何错误记录到由错误日志定义的文件或系统日志中。这在生产环境中非常有用,因为您可以记录发生的错误,然后根据这些错误生成报告。
如果PHP的默认错误处理不充分,您还可以使用自己的自定义错误处理程序处理许多类型的错误,方法是使用set_error_handler()
安装它。虽然有些错误类型不能用这种方式处理,但是可以用脚本认为合适的方式处理那些错误:例如,这可以用来向用户显示自定义错误页,然后比通过日志(例如通过发送电子邮件)更直接地报告。
PHP 7 错误处理
PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error 异常抛出。
这种 Error 异常可以像 Exception 异常一样被第一个匹配的try/catch块所捕获。如果没有匹配的catch块,则调用异常处理函数(事先通过 set_exception_handler() 注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。
Error 类并非继承自 Exception 类,所以不能用catch (Exception $e) { ... }
来捕获 Error。你可以用catch (Error $e) { ... }
,或者通过注册异常处理函数(set_exception_handler()
)来捕获 Error。
Error 层次结构
- Throwable
- Error
- ArithmeticError
- DivisionByZeroError
- AssertionError
- CompileError
- ParseError
- TypeError
- ArgumentCountError
- ArithmeticError
- Exception
- ...
- Error
You can catch both exceptions and errors by catching(Throwable)
Throwable does not work on PHP 5.x. To catch both exceptions and errors in PHP 5.x and 7, add a catch block for Exception AFTER catching Throwable first. Once PHP 5.x support is no longer needed, the block catching Exception can be removed. try { // Code that may throw an Exception or Error. } catch (Throwable $t) { // Executed only in PHP 7, will not match in PHP 5 } catch (Exception $e) { // Executed only in PHP 5, will not be reached in PHP 7 }
An excellent blog post on the difference between exceptions, throwables and how PHP 7 handles these can be found here: https://trowski.com/2015/06/24/throwable-exceptions-and-errors-in-php7/
php 7.1 try { // Code that may throw an Exception or ArithmeticError. } catch (ArithmeticError | Exception $e) { // pass }
<?php set_error_handler(function(int $number, string $message) { echo "Handler captured error $number: '$message'" . PHP_EOL ; }); try { echo $x; # notice, handled on callable pg_exec(null, null); # warning, handled on callable fho(); # fatal error, stop running and catched } catch (Throwable $e) { echo "Captured Throwable: " . $e->getMessage() . PHP_EOL; } ?> set_error_handler will also works without try and catch