PHP的错误和异常处理
PHP程序的错误发生一般归属于下列三个领域。
语法错误
语法错误最常见,并且最容易修复。例如,遗漏了一个分号,就会显示错误信息。这类错误会阻止脚本执行。通常发生在程序开发时,可以通过错误报告进行修复,再重新运行。
Ø 运行时错误
这种错误一般不会阻止PHP脚本的运行,但是会阻止脚本做希望它所做的任何事情。例如,在调用header()函数前如果有字符输出,PHP通常会显示一条错误消息,虽然PHP脚本继续运行,但header()函数并没有执行成功。
Ø 逻辑错误
这种错误实际上是最麻烦的,不但不会阻止PHP脚本的执行,也不会显示出错误消息。例如,在if语句中判断两个变量的值是否相等,如果错把比较运行符号“==”写成赋值运行符号“=”就是一种逻辑错误,很难会被发现。
一个异常则是在一个程序执行过程中出现的一个例外,或是一个事件,它中断了正常指令的运行,跳转到其他程序模块继续执行。所以异常处理经常被当做程序的控制流程使用。无论是错误还是异常,应用程序都必须能够以妥善的方式处理,并做出相应的反应,希望不要丢失数据或者导致程序崩溃。
1.错误的类型
运行PHP脚本时,PHP解析器会尽其所能地报告它遇到的问题。在PHP中错误报告的处理行为,都是通过PHP的配置文件php.ini中有关的配置指令确定的。另外PHP的错误报告有很多种级别,可以根据不同的错误报告级别提供对应的调试方法。一旦把PHP设置成呈现出发生了哪些错误,你可能想调整错误报告的级别。
级别常量 |
错误报告描述 |
E_ERROR |
致命的运行时错误(它会阻止脚本的执行) |
E_WARNING |
运行时警告(非致命的错误) |
E_PARSE |
从语法中解析错误 |
E_NOTICE |
运行时注意消息(可能是或者可能不是一个问题) |
E_CORE_ERROR |
类似E_ERROR,但不包括PHP核心造成的错误 |
E_CORE_WARNING |
类似E_WARNING,但不包括PHP核心错误警告 |
E_COMPILE_ERROR |
致命的编译时错误 |
E_COMPILE_WARNING |
致命的编译时警告 |
E_USER_ERROR |
用户导致的错误消息 |
E_USER_WARNING |
用户导致的警告 |
E_USER_NOTICE |
用户导致的注意消息 |
E_ALL |
所有的错误、警告和注意 |
E_STRICT |
关于PHP版本移植的兼容性和互操作性建议 |
如果用户希望在PHP脚本中,遇到上表中的某个级别的错误时,将错误消息报告给用户。则必须在配置文件php.ini中,将display_errors指令的值设置为On,开启PHP输出错误报告的功能。也可以在PHP脚本中调用ini_set()函数,动态设置配置文件php.ini中的某个指令。如果display_errors被启用,就会显示满足已设置的错误级别的所有错误。当用户在访问时,看到显示的这些消息不仅会感到迷惑,而且还可能会过多地泄露有关服务器的信息,使服务器变得很不安全。所以在项目开发或测试期间启用此指令,可以根据不同的错误报告更好的调试程序。出于安全性和美感的目的,让公众用户查看PHP的详细出错消息一般是不明智的,所以在网站投入使用时要将其禁用。
2.显示错误报告的级别
Ø 可以通过在配置文件php.ini中,修改配置指令error_reporting的值,修改成功后重新启动Web服务器,则每个PHP脚本都可以按调整后的错误级别输出错误报告。下面是修改php.ini配置文件的示例,列出几种为error_reporting指令设置不同级别值的方式,可以把位运算符[&(与)、|(或)、~(非)]和错误级别常量一起使用。如下所示:
; 可以抛出任何非注意的错误,默认值 error_reporting = E_ALL & ~E_NOTICE ; 只考虑致命的运行时错误、解析错误和核心错误 ; error_reporting = E_ERROR | E_PARSE | E_CORE_ERROR ; 报告除用户导致的错误之外的所有错误 ; error_reporting = E_ALL & ~(E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE) |
Ø 或者可以在PHP脚本中使用error_reporting()函数,基于各个脚本来调整这种行为。这个函数用于确定PHP应该在特定的页面内报告哪些类型的错误。该函数获取一个数字或上表中错误级别常量作为参数。如下所示:
<DIV align=center>
error_reporting(0); //设置为0会完全关闭错误报告 error_reporting (E_ALL); //将会向PHP报告发生的每个错误 error_reporting (E_ALL & ~E_NOTICE); //可以抛出任何非注意的错误报告 |
3.错误日志
对于PHP开发者来说,一旦某个产品投入使用,应该立即将display_errors选项关闭,以免因为这些错误所透露的路径、数据库连接、数据表等信息而遭到黑客攻击。但是,任何一个产品在投入使用后,都难免会有错误出现,那么如何记录一些对开发者有用的错误报告呢?我们可以在单独的文本文件中将错误报告作为日志记录。错误日志的记录,可以帮助开发人员或者管理人员查看系统是否存在问题。
如果需要将程序中的错误报告写入错误日志中,只要在PHP的配置文件中,将配置指令log_errors开启即可。错误报告默认就会记录到Web服务器的日志文件里,例如记录到Apache服务器的错误日志文件error.log中。当然也可以记录错误日志到指定的文件中或发送给系统syslog,分别介绍如下:
1.使用指定的文件记录错误报告日志
如果使用自己指定的文件记录错误日志,一定要确保将这个文件存放在文档根目录之外,以减少遭到攻击的可能。并且该文件一定要让PHP脚本的执行用户(Web服务器进程所有者)具有写权限。假设在Linux操作系统中,将/usr/local/目录下的error.log文件作为错误日志文件,并设置Web服务器进程用户具有写的权限。然后在PHP的配置文件中,将error_log指令的值设置为这个错误日志文件的绝对路径。需要将php.ini中的配置指令做如下修改。
error_reporting = E_ALL ;将会向PHP报告发生的每个错误 display_errors = Off ;不显示满足上条指令所定义规则的所有错误报告 log_errors = On ;决定日志语句记录的位置 log_errors_max_len = 1024 ;设置每个日志项的最大长度 error_log = /usr/local/error.log ;指定产生的错误报告写入的日志文件位置 |
PHP的配置文件按上面的方式设置完成以后,并重新启动Web服务器。这样,在执行PHP的任何脚本文件时,所产生的所有错误报告都不会在浏览器中显示,而会记录在自己指定的错误日志/usr/local/error.log中。此外,不仅可以记录满足error_reporting所定义规则的所有错误,而且还可以使用PHP中的error_log()函数,送出一个用户自定义的错误信息。该函数的原型如下所示:
<DIV align=center>
bool error_log ( string message [, int message_type [, string destination [, string extra_headers]]] ) |
error_log("Oracle数据库不可用!", 0); //将错误消息写入到操作系统日志中
error_log("出现大麻烦了!", 1, "webmaster@www.mydomain.com"); //发送到管理员邮箱中
error_log("搞砸了!", 2, "localhost:5000"); //发送到本机对应5000端口的服务器中
error_log("搞砸了!", 3, "/usr/local/errors.log"); //发送到指定的文件中