异常类
本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 66 课,共 91 课。
在 PHP 中,异常是用于表示程序运行过程中出现问题的对象。所有异常的基类都是 Exception,了解它的结构有助于你在面向对象编程应用中有效地处理错误。
抛出异常时,你会创建 Exception 类(或其子类)的一个实例,并附上描述出错原因的消息:
<?php
class BankAccount {
public function __construct(private float $balance = 0) {}
public function withdraw(float $amount): float {
if ($amount > $this->balance) {
throw new Exception("Insufficient funds");
}
$this->balance -= $amount;
return $amount;
}
}
$account = new BankAccount(100);
$account->withdraw(150);
这会产生一个未捕获的异常错误,错误消息为 "Insufficient funds"。
PHP 为不同情况提供了多个内置异常类。InvalidArgumentException 表示输入无效,RuntimeException 表示执行期间发生错误,LogicException 表示编程错误:
<?php
class Calculator {
public function divide(int $a, int $b): float {
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
}
每个异常对象都包含有用的信息:getMessage() 返回错误消息,getCode() 返回可选的错误代码,getFile() 和 getLine() 会告诉你异常是在哪里抛出的。使用具体的异常类型可以让代码意图更清晰,也能更精确地处理错误。
挑战
简单让我们构建一个库存管理系统,使用 PHP 内置的异常类来表示不同类型的问题。你将创建一个产品库存系统,其中的操作可能会以特定且有意义的方式失败。
你将把代码分成 3 个文件:
Product.php:创建一个Product类,用来表示库存中的商品。使用构造函数属性提升,定义一个 public$sku(string)、一个 public$name(string)和一个 private$quantity(int)。你的类应包含:- 一个方法
getQuantity(): int,用于返回当前数量 - 一个方法
addStock(int $amount): void,用于增加数量。如果数量小于 1,则抛出InvalidArgumentException异常,错误消息为"Amount must be positive" - 一个方法
removeStock(int $amount): void,用于减少数量。如果数量小于 1,则抛出InvalidArgumentException异常,错误消息为"Amount must be positive"。如果数量超过当前数量,则抛出RuntimeException异常,错误消息为"Insufficient stock"
- 一个方法
Inventory.php:创建一个Inventory类,用于管理一组商品。引入 Product 文件。你的类应包含:- 一个 private 数组,用于按 SKU 存储商品
- 一个方法
addProduct(Product $product): void,用于添加商品。如果已经存在 SKU 相同的商品,则抛出LogicException异常,错误消息为"Product already exists: [sku]" - 一个方法
getProduct(string $sku): Product,用于按 SKU 返回商品。如果找不到商品,则抛出InvalidArgumentException异常,错误消息为"Product not found: [sku]"
main.php:引入 Inventory 文件。你会收到 3 个输入:SKU、商品名称和一个操作("add"、"remove"或"duplicate")。创建一个
Inventory,并使用给定的 SKU、名称和初始数量10添加一个新的Product。根据操作执行相应的步骤:
"add":对商品调用addStock(5),然后打印"Stock updated: [quantity]""remove":对商品调用removeStock(15)(这应该会抛出异常)"duplicate":尝试添加另一个 SKU 相同的商品(这应该会抛出异常)
抛出异常时,打印异常的类名,后面接
": "和异常消息。使用 PHP 的get_class()函数获取类名。
这个挑战展示了不同类型的异常如何表示不同的问题,包括无效输入、运行时故障和逻辑错误,让你的代码能够更准确、更清晰地处理错误。
亲手试试
<?php
require_once 'Inventory.php';
// 读取输入
$sku = trim(fgets(STDIN));
$name = trim(fgets(STDIN));
$operation = trim(fgets(STDIN));
try {
// TODO: 创建一个 Inventory 对象
// TODO: 创建一个 Product 对象,使用给定的 SKU、名称和初始数量 10
// TODO: 将商品添加到库存中
// TODO: 根据操作执行以下步骤:
// “add”:对商品调用 addStock(5),然后打印 "Stock updated: [quantity]"
// “remove”:对商品调用 removeStock(15)
// “duplicate”:尝试添加另一个具有相同 SKU 的商品
} catch (Exception $e) {
// TODO: 打印异常类名,后面接 ": " 和异常消息
// 提示:使用 get_class($e) 获取类名
}
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: PHP 在线编译器