PDOException是PHP中专门用于处理PDO数据库操作错误的异常类,继承自PHP内置的Exception类。下面我将详细介绍PDOException的组成部分,并通过完整的闭环示例展示其使用方式。
PDOException的核心组成
属性部分:
public array $errorInfo:相当于PDO::errorInfo()或PDOStatement::errorInfo()返回的错误信息数组protected string $message:文本错误信息,可通过Exception::getMessage()访问protected string $code:SQLSTATE错误码,可通过Exception::getCode()访问继承的方法:
getMessage():获取错误消息getCode():获取错误代码getFile()和getLine():获取发生异常的文件和行号getTrace()和getTraceAsString():获取调用堆栈信息
PDOException的使用场景
数据库连接失败:
try {
$pdo = new PDO('mysql:host=localhost;dbname=nonexistent_db', 'root', '');
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
// 记录错误日志或执行其他错误处理逻辑
}当数据库连接失败时(如数据库不存在或用户权限不足),会抛出PDOException。
SQL执行失败:
try {
$stmt = $pdo->prepare("SELECT * FROM nonexistent_table");
$stmt->execute();
} catch (PDOException $e) {
echo "Query failed: " . $e->getMessage();
// 可以在这里回滚事务或执行其他恢复操作
}当SQL语句执行失败时(如表不存在或语法错误),会抛出PDOException。
事务处理失败:
try {
$pdo->beginTransaction();
$pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
$pdo->commit();
} catch (PDOException $e) {
$pdo->rollBack();
echo "Transaction failed: " . $e->getMessage();
}在事务处理过程中,如果某个操作失败,可以捕获PDOException并回滚事务。
预处理语句绑定参数错误:
try {
$stmt = $pdo->prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
$stmt->bindValue(':name', 'John');
$stmt->bindValue(':age', 'invalid_age'); // 类型不匹配
$stmt->execute();
} catch (PDOException $e) {
echo "Parameter binding failed: " . $e->getMessage();
}当预处理语句绑定参数时出现类型不匹配或其他错误,会抛出PDOException。
完整闭环示例
下面是一个完整的PDOException处理示例,包含数据库连接、查询和事务处理:
<?php
// 设置错误模式为异常模式
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
];
try {
// 1. 数据库连接
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password', $options);
// 2. 简单查询
$stmt = $pdo->query("SELECT * FROM users WHERE id = 1");
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// 3. 事务处理
$pdo->beginTransaction();
try {
// 更新用户余额
$updateStmt = $pdo->prepare("UPDATE accounts SET balance = balance - :amount WHERE user_id = :userId");
$updateStmt->execute([':amount' => 100, ':userId' => 1]);
// 记录交易
$insertStmt = $pdo->prepare("INSERT INTO transactions (user_id, amount, type) VALUES (:userId, :amount, 'debit')");
$insertStmt->execute([':userId' => 1, ':amount' => 100]);
$pdo->commit();
echo "Transaction completed successfully!";
} catch (PDOException $e) {
$pdo->rollBack();
echo "Transaction failed: " . $e->getMessage();
// 可以记录更详细的错误信息
error_log("Transaction error: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine());
}
} catch (PDOException $e) {
echo "Database error: " . $e->getMessage();
// 可以记录更详细的错误信息
error_log("Database connection error: " . $e->getMessage() . " [Error Code: " . $e->getCode() . "]");
}
?>错误处理模式设置
PDO提供三种错误处理模式,推荐使用异常模式(ERRMODE_EXCEPTION):
静默模式(ERRMODE_SILENT):默认模式,只设置错误码,需手动检查
警告模式(ERRMODE_WARNING):除设置错误码外,还发出E_WARNING
异常模式(ERRMODE_EXCEPTION):抛出PDOException异常,推荐使用
设置方式:
// 初始化时设置 $pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); // 或初始化后设置 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
通过合理使用PDOException,可以构建更健壮、更安全的数据库应用程序。