在PHP项目里,异常类型往往随着业务增长不断变多。如果每次都写死catch某个具体异常类,代码会变得越来越臃肿。通过把需要捕获的异常类型放到配置中,在运行时动态决定捕获哪些异常,可以让异常处理逻辑更清晰也更容易维护。

为什么需要动态异常类型捕获
传统写法如下,只能捕获固定类型:
try {
// 可能抛出风险的业务代码
doSomething();
} catch (AppExceptionNetworkException $e) {
logError($e->getMessage());
} catch (AppExceptionDbException $e) {
logError($e->getMessage());
}
当异常种类变多,这种结构会不断膨胀。可配置方式则把类型列表外置。
配置驱动的实现方式
先把要捕获的异常类写在配置数组里:
<?php
// config/exception.php
return [
'catch_types' => [
'AppExceptionNetworkException',
'AppExceptionDbException',
'AppExceptionValidateException',
],
];
接着在统一异常处理函数中动态生成catch逻辑:
<?php
function handleByConfig(callable $task, array $types) {
try {
return $task();
} catch (Throwable $e) {
foreach ($types as $type) {
if ($e instanceof $type) {
// 动态匹配异常类型并处理
error_log('捕获到配置异常: ' . $type . ' - ' . $e->getMessage());
return false;
}
}
// 不在配置内的异常重新抛出
throw $e;
}
}
$config = require __DIR__ . '/config/exception.php';
$result = handleByConfig(function () {
// 模拟抛出一个配置中的异常
throw new AppExceptionDbException('数据库连接失败');
}, $config['catch_types']);
使用变量类名的注意点
- 异常类必须真实存在且可自动加载,否则instanceof判断会触发错误。
- 配置中的类字符串不要带多余空格,避免匹配失效。
- 建议把通用异常放在配置末尾,特殊异常靠前以提升可读性。
结合工厂模式优化
如果不同异常需要不同处理策略,可以用工厂返回处理器:
<?php
class HandlerFactory {
public static function make(string $type) {
$map = [
'AppExceptionNetworkException' => NetworkHandler::class,
'AppExceptionDbException' => DbHandler::class,
];
$handlerClass = $map[$type] ?? DefaultHandler::class;
return new $handlerClass();
}
}
这样配置只管捕获,处理细节交给对应类,整体结构更松耦合。
小结
把异常类型放到配置中,再通过instanceof动态判断,是PHP里实现可配置异常捕获的实用做法。它让业务代码少改动,也方便运维人员调整容错范围。