10.5 PHP错误和异常处理
无论是初学者还是经验丰富的程序员,编写的程序都可能存在各种各样的错误,这些错误会降低软件的稳定性,PHP中提供了完善的错误和异常处理机制。
10.5.1 PHP的错误处理机制
在PHP 4中,没有异常Exception这个概念,只有错误Error。可以通过修改php.ini文件来配置用户端输出的错误信息。
在php.ini中,一个分号“;”表示注释。下面列出几种常用的类型。
(1);E_ALL:所有的错误和警告。
(2);E_ERROR:致命的运行时错误。
(3);E_RECOVERABLE_ERROR:几乎致命的运行时错误。
(4);E_WARNING :运行时的警告(非致命错误)。
(5);E_PARSE:编译时解析错误。
(6);E_NOTICE:运行时的提示,这些提示常常是由代码中的bug引起的。
在php.ini中,error_reporting控制输出到用户端的消息种类。可以把上面的类型自由组合然后斌值给error_reporting。例如:
error_reporting = E_ALL表示输出所有的信息。
error_reporting = E_ALL & ~E_NOTICE表示输出所有的错误,除了提示。
在php.ini中,display_errors可以设置是否将以上设置的错误信息输出到用户端。
display_errors = On输出到用户端(调试代码时候,打开这项更方便)。
display_errors = Off消息将不会输出到用户端(最终发布时应改成Off)。
除了在php.ini文件中可以调整错误消息的显示级别外,在PHP代码中也可以自定义消息显示的级别。PHP提供了一个方便的调整函数:
int error_reporting ( [int level] )
使用这个函数可以定义当前PHP页面中错误消息的显示级别。参数level使用了二进制掩码组合的方式。
错误类型见表10-5。
错误类型 | 对应值 |
E_ERROR | 1 |
E_WARNING | 2 |
E_PARSE | 4 |
E_NOTICE | 8 |
E_CORE_ERROR | 16 |
E_CORE_WARNING | 32 |
E_COMPILE_ERROR | 64 |
E_COMPILE_WARNING | 128 |
E_USER_ERROR | 256 |
E_USER_WARNING | 512 |
E_USER_NOTICE | 1024 |
E_ALL | 2047 |
E_STRICT | 2048 |
E_RECOVERABLE_ERROR | 4096 |
例10-8 显示所有错误,代码如下。
<?php //显示所有错误 error_reporting(E_ALL); echo $a; echo '<br>'; echo 'ok'; ?>
结果提示$a变量未定义,输出如图10-7所示。
例10-9 显示所有错误,除了提示,代码如下。
<?php //显示所有错误,除了提示 error_reporting(E_ALL^E_NOTICE); echo $a; echo '<br>'; echo 'ok'; ?>
结果会顺利通过编译,最后输出如图10-8所示。
例10-10 出现警告,代码如下。
<?php //出现警告 error_reporting(E_ALL); echo 2/0; ?>
最后会出现警告,如图10-9所示。
例10-11 显示所有错误,除了警告,代码如下。
<?php //显示所有错误,除了警告 error_reporting(E_ALL^E_WARNING); echo 2/0; echo '<br>'; echo 'ok'; ?>
结果会顺利通过编译输出,结果如图10-10所示。
10.5.2 自定义错误处理
可以使用set_error_handler函数自定义错误处理函数,然后使用trigger_error函数来触发自定义函数。
例10-12 自定义错误处理。
<?php //自定义错误处理函数 function customError($errno, $errstr, $errfile, $errline) { echo "<b>Custom error:</b> [$errno] $errstr<br />"; echo " Error on line $errline in $errfile<br />"; echo "Ending Script"; die(); } //set error handler set_error_handler("customError"); $test=0; //trigger error if ($test==0) { trigger_error("A custom error has been triggered"); }else{ echo intval(100/$test); } ?>
结果输出如图10-11所示。
10.5.3 PHP异常处理
异常处理是PHP 5中新增的更高的错误处理机制,它会在指定的错误发生时改变脚本的正常流程,是PHP 5提供的一种新的面向对象的错误处理方法。
1.异常的抛出与捕获
PHP 5中使用try…catch语句捕获并处理异常。使用异常的函数应该位于try代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。throw语句规定如何触发异常。每一个throw必须对应至少一个catch,catch代码块会捕获异常,并创建一个包含异常信息的对象。语法如下。
try{ //可能引发异常的语句 }catch(异常类型 异常实例){ //异常处理语句 }
当异常被抛出时,其后的代码不会继续执行,PHP会尝试查找匹配的catch代码块。如果异常没有被捕获,而且又没用使用set_exception_handler()做相应的处理的话,那么将发生一个严重的错误(致命错误),并且输出“Uncaught Exception”(未捕获异常)的错误消息。
例10-13 异常的使用,代码如下。
<?php //创建可抛出一个异常的函数 function checkNum($number) { if($number>1) { throw new Exception("参数必须<=1"); } return true; } //在try代码块中触发异常 try { checkNum(2); } //捕获异常 catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?>
结果输出如图10-12所示。
2.基本异常类介绍
PHP的基本异常(Exception)类是PHP 5的一个基本内置类,该类用于脚本发生异常时,创建异常对象,该对象用于存储异常信息及抛出和捕获。Exception类的构造方法需要接收两个参数:错误信息与错误代码,如下。
class Exception { protected $message = 'Unknown exception'; //异常信息 protected $code = 0; //用户自定义异常代码 protected $file; //发生异常的文件名 protected $line; //发生异常的代码行号 function __construct($message = null, $code = 0); final function getMessage(); //返回异常信息 final function getCode(); //返回异常代码 final function getFile(); //返回发生异常的文件名 final function getLine(); //返回发生异常的代码行号 final function getTrace(); //backtrace() 数组 final function getTraceAsString(); //已格成化成字符串的 getTrace() 信息 /* 可重载的方法 */ function __toString(); //可输出的字符串 }
3.自定义异常
PHP 5中可以自定义异常,自定义的异常必须继承自Exception类或者它的子类。
例10-14 自定义异常,代码如下。
<?php class emailException extends Exception{ public function errorMessage() { //异常信息 $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() .': <br>'.$this->getMessage().'不是合法的Email'; return $errorMsg; } } $email = "usrname@HBSI...com"; try { if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //邮件不合法,抛出异常 throw new emailException($email); } }catch (emailException $e){ //显示自定义的错误信息 echo $e->errorMessage(); } ?>
最后输出如图10-13所示。
4.捕获多个异常
PHP 5中可以使用多个来catch接收多个异常。
例10-15 接收多个异常,代码如下。
<?php class emailException extends Exception{ public function errorMessage() { //异常信息 $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() .': <br>'.$this->getMessage().'不是合法的Email'; return $errorMsg; } } $email = "HBSI@example..com"; try { if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //抛出异常 throw new emailException($email); } //检测是否是示例邮件 if(strpos($email, "example") !== FALSE) { throw new Exception("邮件是一个示例邮件"); } } catch (emailException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>
最后输出如图10-14所示。
如果将邮件换成$email = "HBSI@example..com",结果输出如图10-15所示。