PHP 异常处理
在本教程中,您将学习如何在PHP中引发和捕获异常。
什么是异常
异常是表示发生某种异常事件或错误的信号。可能由于多种原因导致异常,例如,数据库连接或查询失败,您尝试访问的文件不存在等等。
PHP提供了强大的异常处理机制,使您能够以优美的方式处理异常。与PHP的传统错误处理系统相反,异常处理是一种用于处理错误面向对象的方法,它提供了更具指定性和灵活性的错误报告形式。异常模型最早是在PHP 5中引入的。
使用Throw 和 Try ... Catch语句
在基于异常的方法中,程序代码编写在try块中,当在try块中执行代码期间发生异常事件时,可以使用throw语句引发异常。 然后由一个或多个捕获块捕获并解析它。
下面的示例演示异常处理如何工作:
<?php function division($dividend, $divisor){ //如果除数为零,则抛出异常 if($divisor == 0){ throw new Exception('Division by zero.'); } else{ $quotient = $dividend / $divisor; echo "<p>$dividend / $divisor = $quotient</p>"; } } try{ division(10, 2); division(30, -4); division(15, 0); //如果抛出异常,后面的行将不会执行 echo '<p>所有的均成功执行。</p>'; } catch(Exception $e){ //处理异常 echo "<p>捕获的异常: " . $e->getMessage() . "</p>"; } // 继续执行 echo "<p>Hello World!</p>"; ?>
您可能想知道这段代码是关于什么的。好吧,让我们逐一遍历此代码的每个部分,以更好地理解。
代码的用法解释
在PHP的异常处理系统有四种基本部分:try,throw,catch,和Exception类。以下列表描述了各个部分的工作原理。
上例中的division()函数检查除数是否等于零。如果是,则通过PHP的throw语句抛出异常。否则,此函数使用给定的数字执行除法并显示结果。
然后,在try块中使用不同的参数调用division()函数。如果在try块中执行代码时生成异常,PHP将在该点停止执行并尝试查找相应的catch块。如果找到,则执行catch块中的代码,否则生成致命错误。
catch块通常捕获try块中抛出的异常,并创建一个包含异常信息的对象($e)。可以使用异常的getMessage()方法检索来自此对象的错误消息。
在PHP的异常类也提供了getCode(),getFile(),getLine()和getTraceAsString()可用于生成详细的调试信息的方法。
<?php //关闭默认错误报告 error_reporting(0); try{ $file = "somefile.txt"; //尝试打开文件 $handle = fopen($file, "r"); if(!$handle){ throw new Exception("无法打开文件!", 5); } //尝试读取文件内容 $content = fread($handle, filesize($file)); if(!$content){ throw new Exception("Could not read file!", 10); } //关闭文件句柄 fclose($handle); //显示文件内容 echo $content; } catch(Exception $e){ echo "<h3>Caught Exception!</h3>"; echo "<p>Error message: " . $e->getMessage() . "</p>"; echo "<p>File: " . $e->getFile() . "</p>"; echo "<p>Line: " . $e->getLine() . "</p>"; echo "<p>Error code: " . $e->getCode() . "</p>"; echo "<p>Trace: " . $e->getTraceAsString() . "</p>"; } ?>
异常的构造函数可以选择接受异常消息和异常代码。 虽然异常消息通常用于显示出错原因的一般信息,但异常代码可用于对错误进行分类。 稍后可以通过Exception的getCode()方法检索提供的异常代码。
提示:异常仅应用于表示特殊情况;它们不应用于指定正常的应用程序流程,例如,在特定位置跳转到脚本中的其他位置。这样做会不利地影响应用程序的性能。
定义自定义异常
您甚至可以定义自己的自定义异常处理程序,以不同的方式处理不同类型的异常。 它允许您为每种异常类型使用单独的catch块。
您可以通过扩展Exception类来定义自定义异常,因为Exception是所有异常的基类。 自定义异常类继承了PHP Exception类的所有属性和方法。 您还可以将自定义方法添加到自定义异常类。 让我们看一下以下示例:
<?php //扩展Exception类 class EmptyEmailException extends Exception {} class InvalidEmailException extends Exception {} $email = "someuser@example..com"; try{ //如果电子邮件为空,则抛出异常 if($email == ""){ throw new EmptyEmailException("<p>请输入您的电子邮件地址!</p>"); } //如果电子邮件无效,则抛出异常 if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { throw new InvalidEmailException("<p><b>$email</b> 不是有效的电子邮件地址!</p>"); } // 如果电子邮件有效,则显示成功消息 echo "<p>成功:电子邮件验证成功.</p>"; } catch(EmptyEmailException $e){ echo $e->getMessage(); } catch(InvalidEmailException $e){ echo $e->getMessage(); } ?>
在上面的示例中,我们从Exception基类派生了两个新的异常类:EmptyEmailException和InvalidEmailException。 多个捕获块用于显示不同的错误消息,具体取决于生成的异常类型。
由于这些自定义异常类继承了Exception类的属性和方法,所以我们可以使用异常的类方法,如getMessage(),getLine(),getFile(),等来检索异常对象的错误信息。
设置全局异常处理程序
如本章前面所讨论的,如果未捕获到异常,则PHP会生成一条致命错误,并带有“ Uncaught Exception ...”消息。 此错误消息可能包含敏感信息,例如出现问题的文件名和行号。 如果您不想向用户公开此类信息,则可以创建一个自定义函数,并向set_exception_handler()函数注册该函数以处理所有未捕获的异常。
<?php function handleUncaughtException($e){ //向用户显示一般错误消息 echo "哎呀!出了点问题。请重试,如果问题仍然存在,请与我们联系。"; // 构造错误字符串 $error = "Uncaught Exception: " . $message = date("Y-m-d H:i:s - "); $error .= $e->getMessage() . " in file " . $e->getFile() . " on line " . $e->getLine() . "\n"; //在文件中记录错误的详细信息 error_log($error, 3, "var/log/exceptionLog.log"); } //注册自定义异常处理程序 set_exception_handler("handleUncaughtException"); // 抛出异常 throw new Exception("Testing Exception!"); ?>
注意:未捕获的异常总是会导致脚本终止。 因此,如果希望脚本在异常发生点之后继续执行,则每个try块必须至少有一个对应的catch块。