创建自定义异常
扩展 Exception 类,构建特定领域的错误类型。
创建自定义异常 是 CoddyKit 上的免费 PHP Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 PHP Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 PHP Academy 课程共包含 4 节课。
为什么要使用自定义异常?
自定义异常可以让您:
- 将应用程序错误与通用 PHP 错误区分开
- 携带特定领域的数据(订单 ID、用户 ID 等)
- 在不同层中捕获特定的错误类型
- 创建有意义且能自我说明的错误层次结构
扩展 Exception
通过扩展 Exception 基类创建自定义异常:
<?php
class ValidationException extends \Exception
{
private array $errors;
public function __construct(array $errors, string $message = '', int $code = 0)
{
$this->errors = $errors;
parent::__construct($message ?: implode(', ', $errors), $code);
}
public function getErrors(): array
{
return $this->errors;
}
}使用自定义异常
抛出并捕获您的自定义异常:
<?php
function createUser(array $data): void {
$errors = [];
if (empty($data['email'])) $errors[] = 'Email required';
if (empty($data['name'])) $errors[] = 'Name required';
if ($errors) {
throw new ValidationException($errors);
}
// save user...
}
try {
createUser([]);
} catch (ValidationException $e) {
foreach ($e->getErrors() as $err) {
echo '- ' . $err . PHP_EOL;
}
}异常层次结构设计
为您的领域设计层次结构:
<?php
// Base exception for your app
class AppException extends \RuntimeException {}
// Domain-specific exceptions
class NotFoundException extends AppException {}
class AuthException extends AppException {}
class PaymentException extends AppException {}
// Specific payment errors
class InsufficientFundsException extends PaymentException {
public function __construct(public readonly float $balance, public readonly float $required) {
parent::__construct("Insufficient funds: have $balance, need $required");
}
}按层次结构捕获
捕获基类即可处理所有派生异常:
<?php
try {
processPayment($order);
} catch (InsufficientFundsException $e) {
echo 'Low balance: need ' . $e->required;
} catch (PaymentException $e) {
echo 'Payment failed: ' . $e->getMessage();
} catch (AppException $e) {
echo 'App error: ' . $e->getMessage();
} catch (\Throwable $e) {
// Last resort
error_log($e);
}为异常添加上下文
为异常添加额外数据,以便调试:
<?php
class HttpException extends \RuntimeException
{
public function __construct(
private int $statusCode,
string $message = '',
?\Throwable $previous = null
) {
parent::__construct($message, $statusCode, $previous);
}
public function getStatusCode(): int
{
return $this->statusCode;
}
}HTTP 异常示例
在 Web 应用程序中使用 HTTP 异常:
<?php
try {
$user = findUserById($id);
if (!$user) throw new HttpException(404, 'User not found');
if (!$user->canAccess($resource)) {
throw new HttpException(403, 'Access denied');
}
} catch (HttpException $e) {
http_response_code($e->getStatusCode());
echo json_encode(['error' => $e->getMessage()]);
}基于接口的异常
使用接口将互不相关的异常类归为一组:
<?php
interface UserFacingException
{
public function getUserMessage(): string;
}
class ValidationException extends \Exception implements UserFacingException
{
public function getUserMessage(): string
{
return 'Please check your input: ' . $this->getMessage();
}
}
// In controller:
catch (UserFacingException $e) {
echo $e->getUserMessage();
}命名构造器模式
使用静态工厂方法处理常见的异常场景:
<?php
class OrderException extends \RuntimeException
{
public static function notFound(int $id): self
{
return new self("Order #$id not found", 404);
}
public static function alreadyShipped(int $id): self
{
return new self("Order #$id already shipped", 409);
}
}
throw OrderException::notFound($orderId);序列化异常
将异常数据转换为数组,用于日志记录或 API 响应:
<?php
function exceptionToArray(\Throwable $e): array {
return [
'type' => get_class($e),
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString(),
'previous' => $e->getPrevious()
? exceptionToArray($e->getPrevious())
: null,
];
}自定义异常最佳实践
设计自定义异常的指南:
- 对于意外情况,扩展
RuntimeException - 对于程序员错误(无效参数),扩展
LogicException - 不要为每种可能的消息都创建一个异常类 — 应改用代码
- 异常类名称使用 PascalCase,并以 Exception 结尾
- 记录每个方法可能抛出的异常
快速检查
要创建表示代码中逻辑错误的自定义异常,应扩展哪个 PHP 基类?
回顾:自定义异常
自定义异常总结:
- 扩展
Exception或其子类 - 添加特定领域的属性和方法
- 设计层次结构 — 捕获父类即可捕获所有子类
- 使用接口将互不相关的异常归为一组
- 使用静态命名构造器提高可读性
- 始终调用
parent::__construct()
常见问题解答
「创建自定义异常」课时是免费的吗?
是的 — 「创建自定义异常」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 PHP Academy 课程的其余内容,请升级到 CoddyKit PRO。 PHP Academy 课程共包含 4 节课。
「创建自定义异常」这节课中我会学到什么?
扩展 Exception 类,构建特定领域的错误类型。 你通过在浏览器中直接运行的动手代码来练习 PHP Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 PHP Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 PHP Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「创建自定义异常」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 PHP Academy 课中编写并运行代码吗?
能。每节 PHP Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。