PHP 异常处理
在本教程中,您将学习如何在 PHP 中抛出和捕获异常。
什么是异常
异常是表示发生了某种异常事件或错误的信号。 异常可能由多种原因引起,例如数据库连接或查询失败、您尝试访问的文件不存在等等。
PHP 提供了强大的异常处理机制,允许您以优雅的方式处理异常。 与 PHP 传统的错误处理系统相反,异常处理是处理错误的面向对象方法,它提供了更加可控和灵活的错误报告形式。 异常模型最初是在 PHP 5 中引入的。
使用 Throw 和 Try...Catch 语句
在基于异常的方法中,程序代码写在try
块中,当try
块中的代码执行过程中发生异常事件时,可以使用throw
语句抛出异常。 然后它被一个或多个 catch
块捕获和解析。
以下示例演示了异常处理的工作原理:
示例
Download<?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>All divisions performed successfully.</p>';
} catch(Exception $e){
// 处理异常
echo "<p>Caught exception: " . $e->getMessage() . "</p>";
}
// 继续执行
echo "<p>Hello World!</p>";
?>
您可能想知道这段代码是关于什么的。 好吧,让我们一一浏览这段代码的每一部分,以便更好地理解。
代码说明
PHP 的异常处理系统基本上有四个部分:try
, throw
, catch
、Exception 类。 以下列表描述了每个部分的确切工作原理。
- 上例中的
division()
函数检查除数是否等于 0。 如果是,则通过 PHP 的throw
语句引发异常。 否则,此函数使用给定的数字执行除法并显示结果。 - 稍后,在具有不同参数的
try
块中调用division()
函数。 如果在执行try
块中的代码时产生异常,PHP 会在该点停止执行并尝试查找相应的catch
块。 如果找到,则执行该catch
块中的代码,如果没有,则生成致命错误。 catch
块通常捕获在try
块中抛出的异常,并创建一个包含异常信息的对象 ($e
)。 可以使用 Exception 的getMessage()
方法检索来自该对象的错误消息。
PHP 的 Exception 类还提供了 getCode()
、getFile()
、getLine()
和 getTraceAsString()
方法,可用于生成详细的调试信息。
示例
Download<?php
// 关闭默认错误报告
error_reporting(0);
try{
$file = "somefile.txt";
// 尝试打开文件
$handle = fopen($file, "r");
if(!$handle){
throw new Exception("Cannot open the file!", 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 的构造函数可选地接受异常消息和异常代码。 虽然异常消息通常用于显示有关问题的一般信息,但异常代码可用于对错误进行分类。 提供的异常代码可以稍后通过 Exception 的 getCode()
方法检索。
提示: Exception 只能用于表示异常情况; 它们不应用于控制正常的应用程序流程,例如,在特定点跳转到脚本中的另一个位置。 这样做会对您的应用程序的性能产生不利影响。
定义自定义异常
您甚至可以定义自己的自定义异常处理程序,以不同的方式处理不同类型的异常。 它允许您为每种异常类型使用单独的 catch
块。
您可以通过扩展 Exception 类来定义自定义异常,因为 Exception 是所有异常的基类。 自定义异常类继承了 PHP 的 Exception 类的所有属性和方法。 您还可以将自定义方法添加到自定义异常类。 让我们看看下面的例子:
示例
Download<?php
// 扩展异常类
class EmptyEmailException extends Exception {}
class InvalidEmailException extends Exception {}
$email = "someuser@example..com";
try{
// 如果电子邮件为空,则抛出异常
if($email == ""){
throw new EmptyEmailException("<p>Please enter your E-mail address!</p>");
}
// 如果电子邮件无效,则抛出异常
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
throw new InvalidEmailException("<p><b>$email</b> is not a valid E-mail address!</p>");
}
// 如果电子邮件有效,则显示成功消息
echo "<p>SUCCESS: Email validation successful.</p>";
} catch(EmptyEmailException $e){
echo $e->getMessage();
} catch(InvalidEmailException $e){
echo $e->getMessage();
}
?>
在上面的示例中,我们派生了两个新的异常类:EmptyEmailException 和 InvalidEmailException 来自 Exception 基类。 多个 catch
块用于显示不同的错误消息,具体取决于生成的异常类型。
由于这些自定义异常类继承了异常类的属性和方法,所以我们可以使用异常的类方法如 getMessage()
, getLine()
, getFile()
等从异常对象中获取错误信息。
设置全局异常处理程序
正如我们在本章前面所讨论的,如果一个异常没有被捕获,PHP 会生成一个带有"Uncaught Exception ..."消息的致命错误。 此错误消息可能包含敏感信息,例如出现问题的文件名和行号。 如果您不想将此类信息暴露给用户,您可以创建一个自定义函数并将其注册到 set_exception_handler()
函数以处理所有未捕获的异常。
示例
Download<?php
function handleUncaughtException($e){
// 向用户显示一般错误消息
echo "Opps! Something went wrong. Please try again, or contact us if the problem persists.";
// 构造错误字符串
$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
块。