try、catch、finally
本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 68 课,共 91 课。
现在你已经知道如何创建和抛出异常,接下来需要学习如何捕获异常。try-catch-finally 结构可以让你妥善处理异常,而不是让它们导致应用程序崩溃。
将可能抛出异常的代码放在 try 块中,然后在 catch 块中处理异常:
<?php
class Calculator {
public function divide(int $a, int $b): float {
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
}
$calc = new Calculator();
try {
echo $calc->divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage();
}
输出:
Error: Cannot divide by zero你可以用多个 catch 块捕获不同类型的异常。PHP 会按顺序检查它们,所以要把更具体的异常放在前面:
<?php
try {
// 可能出错的代码
} catch (InvalidArgumentException $e) {
echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
echo "Something went wrong: " . $e->getMessage();
}
无论是否抛出或捕获异常,finally 块都会运行。它非常适合执行清理任务,例如关闭连接:
<?php
try {
echo "Attempting operation\n";
throw new Exception("Failed");
} catch (Exception $e) {
echo "Caught: " . $e->getMessage() . "\n";
} finally {
echo "Cleanup complete";
}
输出:
Attempting operation
Caught: Failed
Cleanup complete即使你在 try 或 catch 块中执行 return,finally 块也会执行,因此它适合用于必要的清理操作。
挑战
简单我们来构建一个文件处理系统,演示如何结合使用 try-catch-finally 来妥善处理错误,同时确保始终执行清理操作。
你将把代码分布在三个文件中:
FileException.php:创建一个自定义的FileException类,使其继承Exception。这个类用于表示系统中的文件相关错误。FileProcessor.php:创建一个模拟文件操作的FileProcessor类。引入 FileException 文件。你的类应包含:- 一个私有布尔属性
$isOpen,初始值为false - 一个
open(string $filename): void方法,将$isOpen设置为true,并打印"Opening: [filename]"。如果文件名是"invalid.txt",则抛出一个FileException,错误消息为"Cannot open file" - 一个
process(): void方法,打印"Processing file..."。如果$isOpen为false,则抛出一个RuntimeException,错误消息为"File not open" - 一个
close(): void方法,将$isOpen设置为false,并打印"File closed" - 一个
isOpen(): bool方法,返回当前状态
- 一个私有布尔属性
main.php:引入 FileProcessor 文件。你将收到一个输入:文件名。创建一个
FileProcessor,并使用try-catch-finally结构来完成以下操作:- 在
try代码块中:使用文件名调用open(),然后调用process() - 先捕获
FileException,并打印"File error: [message]" - 捕获
RuntimeException,并打印"Runtime error: [message]" - 在
finally代码块中:使用isOpen()检查文件是否已打开,如果已打开,则调用close()。然后打印"Cleanup complete"
- 在
finally 代码块可确保无论操作成功还是失败,都会执行清理操作。这种模式对于管理文件、数据库连接或网络套接字等资源至关重要,因为无论处理过程中发生什么情况,都必须执行清理操作。
亲手试试
<?php
require_once 'FileProcessor.php';
// 读取输入
$filename = trim(fgets(STDIN));
// TODO:创建一个 FileProcessor 实例
// TODO:使用 try-catch-finally 结构:
// 在 try 块中:用文件名调用 open(),然后调用 process()
// 先捕获 FileException,并打印 "File error: [message]"
// 捕获 RuntimeException,并打印 "Runtime error: [message]"
// 在 finally 块中:用 isOpen() 检查文件是否已打开,如果已打开就调用 close()
// 然后打印 "Cleanup complete"
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: PHP 在线编译器