1.异常概述
异常是一种错误处理机制,用于在发生指定的错误时更改脚本的正常流程。
触发异常时,将保存当前代码状态,并将代码执行切换到预定义的异常处理程序功能(如果有)
根据情况,处理器可以从已保存的代码状态重新开始执行代码,终止脚本执行,或者从代码中的另一个位置继续执行脚本
2.异常的基本用法
当引发异常时,后续代码将不会继续执行,PHP将尝试查找匹配的“ catch”代码块。
如果未捕获到异常,并且不需要使用set_exception_handler()进行相应的处理,则将发生严重错误(致命错误),并且将输出“未捕获异常”错误消息。
尝试引发异常而不捕获异常
//create function with an exception
function checkNum($number){
if($number>1){
throw new Exception("Value must be 1 or below");
}
}
//trigger exception
checkNum(2);
上述的这段代码会获得类似这样的错误:
Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in C:\webfolder\test.php:6
Stack trace: #0 C:\webfolder\test.php(12):checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6
注意:PHP默认为警告模式,如果需要对系统错误使用异常处理机制,则必须在处理代码之前设置错误处理模式
set_error_handler(function(){
throw new Exception('错误!');
});
3、Try, throw 和 catch
正确的处理程序应当包括:
Try - 使用异常的函数应该位于 "try" 代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。
Throw - 这里规定如何触发异常。每一个 "throw" 必须对应至少一个 "catch"
Catch - "catch" 代码块会捕获异常,并创建一个包含异常信息的对象
//创建可抛出一个异常的函数
function checkNum($number){
if($number>1){
throw new Exception("Value must be 1 or below");
}
}
//在 "try" 代码块中触发异常
try{
checkNum(2);
}catch(Exception $e) { //捕获异常
echo 'File: '.$e->getFile().' line: '.$e->getLine().'<br>';
die('Message: '.$e->getMessage());
}
上面代码将获得类似这样一个错误:
File: E:\webdev\www\pdo\3.php line: 7
Message: Value must be 1 or below
代码解析:创建 checkNum() 函数。它检测数字是否大于 1。如果是,则抛出一个异常。在 "try" 代码块中调用 checkNum(),函数checkNum() 函数中的异常被抛出,"catch" 代码块接收到该异常,并创建一个包含异常信息的对象 ($e)。通过从这个 exception 对象输出来自该异常的错误消息
不过,为了遵循“每个 throw 必须对应一个 catch”的原则,可以设置一个顶层的异常处理器来处理漏掉的错误,见第7点
4、创建自定义的异常处理器
创建一个专门的类,当 PHP 中发生异常时,可调用其函数。该类必须是 exception 类的一个扩展。这个自定义的exception 类继承了 PHP 的 exception 类的所有属性,可向其添加自定义的函数。
class customException extends Exception{
public function errorMessage(){
return 'Error on line '.$this->getLine().' in '.$this->getFile().': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
}
}
$email = "someone@example...com";
try{
//使用PHP过滤器验证邮箱有效性
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE){
throw new customException($email);
}
}catch (customException $e){
echo $e->errorMessage();
}
这个新类是旧异常类的副本,外加errorMessage()函数。 仅仅是因为它是旧类的副本,所以它继承了旧类的属性和方法。 我们可以使用异常类的方法,例如getLine(),getFile()和getMessage()。
上面的代码引发异常,并使用自定义异常类捕获该异常:创建errorMessage()函数。 如果电子邮件地址无效,则该函数返回错误消息
5.捕获多个异常
您可以对脚本使用多个异常,以检测多种情况。
您可以使用多个if..else代码块或一个切换代码块,或嵌套多个异常。 这些异常可以使用不同的异常类并返回不同的错误消息:
class customException extends Exception{
public function errorMessage(){
return = 'Error on line '.$this->getLine().' in '.$this->getFile().': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
}
}
$email = "someone@example.com";
try{
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE){
throw new customException($email);
}
//check for "example" in mail address
if(strpos($email, "example") !== FALSE){
throw new Exception("$email is an example e-mail");
}
} catch (customException $e){
echo $e->errorMessage();
}catch(Exception $e){
echo $e->getMessage();
}
上面的代码测试了两个条件。 如果未建立任何条件,则会引发异常:
在第一种情况下,执行“ try”代码块不会引发任何异常。 由于电子邮件中包含字符串“ example”,因此第二种情况将触发异常。 “捕获”代码块将捕获异常并显示相应的错误消息。 如果未捕获customException,则仅捕获基本异常,然后将在此处处理该异常。
6.抛出异常
有时,当引发异常时,您可能希望以不同于标准的方式处理异常。 您可以在“ catch”代码块中再次引发异常。 该脚本应向用户隐藏系统错误。 对于程序员而言,系统错误可能很重要,但用户对其不感兴趣。 为了使用户更容易使用,可以再次抛出带有用户友好消息的异常:
class customException extends Exception{
public function errorMessage(){
return $this->getMessage().' is not a valid E-Mail address.';
}
}
$email = "someone@example.com";
try{
try{
if(strpos($email, "example") !== FALSE){
throw new Exception($email);
}
}catch(Exception $e){
//re-throw exception
throw new customException($email);
}
}catch (customException $e){
//display custom message
echo $e->errorMessage();
上面的代码检测电子邮件地址是否包含字符串“ example”。 如果是这样,请再次引发异常:
将$ email变量设置为有效的电子邮件地址,但使用字符串“ example”。 “ try”代码块包含另一个“ try”代码块,以便可以再次引发异常。 由于电子邮件包含字符串“ example”,因此会触发异常。 “ catch”捕获异常并抛出“ customException”。 捕获到“ CustomException”,并显示错误消息。
如果该异常未在其当前的“ try”代码块中捕获,则它将在更高级别上寻找该捕获代码块。
7.设置顶级异常处理程序
set_exception_handler()函数可以设置一个用户定义的函数来处理所有未捕获的异常
function myException($exception){
echo "<b>Exception:</b> " , $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
以上代码的输出应该类似这样:
Exception: Uncaught Exception occurred
在上面的代码中,不存在 "catch" 代码块,而是触发顶层的异常处理程序。应该使用此函数来捕获所有未被捕获的异常。
但是对于系统自动抛出的错误,会先经过set_error_handler处理并抛出异常才能被set_exception_handler处理
function myException($exception){
echo "<b>Exception:</b> " , $exception->getMessage();
}
set_exception_handler('myException');
set_error_handler(function(){
throw new Exception('错误!');
});
echo 10/0; //触发被除数不能为0的警告
代码执行结果:Exception: 错误!