
本文讲解如何通过 pdo 异常捕获机制,优雅地处理 mysql 唯一约束(如手机号唯一)导致的重复插入问题,并正确显示“已存在”和“添加成功”两类用户友好的提示信息。
在使用 PDO 向 MySQL 插入数据时,若字段(如 telephone)设置了 UNIQUE KEY,当尝试插入重复值会触发 PDOException,错误码为 23000(SQLSTATE:完整性约束违反)。直接抛出原始异常(如 Fatal error...)对用户极不友好。因此,合理使用 try/catch 捕获并分类响应是关键。
但需注意一个常见逻辑误区:else 分支无法在 catch 块中用于表示“插入成功”。因为 catch 仅在异常发生时执行;若插入成功,程序根本不会进入 catch,也就不会执行其中的 else。原代码中将成功提示写在 catch 内部的 else 中,导致该消息永远无法显示——这是根本性逻辑错误。
✅ 正确做法是:将“操作成功”的提示移至 try 块末尾或 catch 外部,并通过状态变量控制流程。推荐以下结构:
$success = false;
try {
$stmt = $pdo->prepare("INSERT INTO subscribers (name, telephone, comment) VALUES (?, ?, ?)");
$stmt->execute([$name, $telephone, $comment]);
$success = true; // 仅当执行无异常时设为 true
} catch (PDOException $e) {
error_log("DB Error: " . $e->getMessage());
if ($e->getCode() === '23000') {
echo '该手机号已被注册,请勿重复提交。';
} else {
// 其他数据库错误(如连接失败、字段超长等)
echo '系统繁忙,请稍后重试。';
}
}
// ✅ 统一在 try/catch 外判断是否成功
if ($success) {
echo '感谢订阅!您已成功加入数据库。';
}? 关键注意事项:
- 不要依赖 catch 中的 else 表示成功,它只处理异常分支;
- 使用布尔标志(如 $success)显式标记执行结果,提升可读性与可维护性;
- 对非 23000 的其他 PDOException 也应有兜底提示,避免暴露敏感错误信息;
- 生产环境建议结合前端表单验证(如 AJAX 预检手机号是否已存在),实现更流畅的用户体验。
通过以上方式,既能拦截唯一键冲突并给出精准提示,又能确保新增成功时的正向反馈准确呈现,真正实现错误可读、流程可控、体验友好。










