1. PDO 一共包含哪些部分?
(1) 核心组成
-
PDO 类:
- 提供与数据库交互的核心功能(如连接、查询、事务管理等)。
-
PDOStatement 类:
- 用于执行预处理语句和查询语句,并获取结果集。
-
异常处理:
- 支持通过
PDOException
捕获数据库操作中的错误。
- 支持通过
-
驱动支持:
- 支持多种数据库驱动(如 MySQL、PostgreSQL、SQLite 等),通过统一接口访问不同数据库。
-
事务管理:
- 提供
beginTransaction()
、commit()
和rollBack()
方法,用于管理事务。
- 提供
2. 使用场景
(1) 数据库连接
- 示例:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
- 场景:
- 连接到数据库以执行查询或更新操作。
(2) 预处理语句
- 示例:
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username"); $stmt->execute(['username' => 'admin']);
- 场景:
- 使用预处理语句防止 SQL 注入。
(3) 数据查询
- 示例:
$results = $pdo->query("SELECT * FROM users")->fetchAll(PDO::FETCH_ASSOC);
- 场景:
- 查询数据库并获取结果集。
(4) 事务管理
- 示例:
$pdo->beginTransaction(); try { $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 (Exception $e) { $pdo->rollBack(); }
- 场景:
- 在需要原子性操作时使用事务(如转账操作)。
3. 底层原理
(1) 数据存储
-
数据库驱动:
- PDO 使用不同的数据库驱动(如
pdo_mysql
、pdo_pgsql
)与底层数据库通信。
- PDO 使用不同的数据库驱动(如
-
SQL 解析与执行:
- 数据库驱动将 SQL 查询传递给数据库服务器执行,并返回结果。
(2) 程序流
当使用 PDO 时,系统会执行以下步骤:
-
创建连接:
- 使用
new PDO()
创建数据库连接。
- 使用
-
准备语句:
- 调用
prepare()
方法准备 SQL 语句。
- 调用
-
绑定参数:
- 将用户输入绑定到预处理语句中。
-
执行查询:
- 调用
execute()
方法执行 SQL 语句。
- 调用
-
获取结果:
- 调用
fetch()
或fetchAll()
方法获取查询结果。
- 调用
-
关闭连接:
- 当脚本结束时,PDO 自动关闭数据库连接。
(3) 数据流
-
写入数据:
- 开发者通过 SQL 语句向数据库写入数据。
-
读取数据:
- 数据库返回查询结果,PDO 将其转换为 PHP 数组或对象。
4. 示例代码及详细注释
以下是一个完整的示例,展示如何使用 PDO 进行数据库操作,并附上详细注释。
<?php
// 创建数据库连接
// 作用:初始化 PDO 实例,连接到数据库。
// 原因:需要通过 PDO 执行数据库操作。
// 知识点:PDO 构造函数接受 DSN(数据源名称)、用户名和密码。
try {
$dsn = "mysql:host=localhost;dbname=test";
$username = "root";
$password = "";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 设置错误模式为抛出异常
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认以关联数组形式获取结果
];
$pdo = new PDO($dsn, $username, $password, $options);
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
// 插入数据
// 作用:插入一条新记录到数据库。
// 原因:演示如何使用预处理语句插入数据。
// 知识点:PDO 的 prepare() 和 execute() 方法,用于安全地执行 SQL。
try {
$stmt = $pdo->prepare("INSERT INTO users (username, email) VALUES (:username, :email)");
$stmt->execute([
':username' => 'john_doe',
':email' => 'john@example.com',
]);
echo "Data inserted successfully.";
} catch (PDOException $e) {
echo "Insert failed: " . $e->getMessage();
}
// 查询数据
// 作用:从数据库中查询所有用户记录。
// 原因:演示如何使用 PDO 查询数据。
// 知识点:PDO 的 query() 方法,用于执行简单的 SQL 查询。
try {
$results = $pdo->query("SELECT * FROM users")->fetchAll();
foreach ($results as $row) {
echo "Username: " . htmlspecialchars($row['username']) . ", Email: " . htmlspecialchars($row['email']) . "<br>";
}
} catch (PDOException $e) {
echo "Query failed: " . $e->getMessage();
}
// 更新数据
// 作用:更新数据库中的一条记录。
// 原因:演示如何使用预处理语句更新数据。
// 知识点:PDO 的 prepare() 和 execute() 方法,用于安全地执行 SQL。
try {
$stmt = $pdo->prepare("UPDATE users SET email = :email WHERE username = :username");
$stmt->execute([
':email' => 'john.doe@example.com',
':username' => 'john_doe',
]);
echo "Data updated successfully.";
} catch (PDOException $e) {
echo "Update failed: " . $e->getMessage();
}
// 删除数据
// 作用:删除数据库中的一条记录。
// 原因:演示如何使用预处理语句删除数据。
// 知识点:PDO 的 prepare() 和 execute() 方法,用于安全地执行 SQL。
try {
$stmt = $pdo->prepare("DELETE FROM users WHERE username = :username");
$stmt->execute([':username' => 'john_doe']);
echo "Data deleted successfully.";
} catch (PDOException $e) {
echo "Delete failed: " . $e->getMessage();
}
// 事务管理
// 作用:确保一组操作要么全部成功,要么全部失败。
// 原因:在需要原子性操作时使用事务(如转账操作)。
// 知识点:PDO 的 beginTransaction()、commit() 和 rollBack() 方法。
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();
echo "Transaction completed successfully.";
} catch (PDOException $e) {
$pdo->rollBack();
echo "Transaction failed: " . $e->getMessage();
}
5. 注意事项
(1) 错误处理
- 推荐设置
PDO::ATTR_ERRMODE
为PDO::ERRMODE_EXCEPTION
,以便捕获错误。
(2) 预处理语句
- 始终使用预处理语句防止 SQL 注入。
(3) 资源释放
- 确保在脚本结束时关闭数据库连接,避免资源泄漏。
6. 程序流和数据流
(1) 程序流
-
创建连接:
- 初始化 PDO 实例,连接到数据库。
-
准备语句:
- 调用
prepare()
方法准备 SQL 语句。
- 调用
-
绑定参数:
- 将用户输入绑定到预处理语句中。
-
执行查询:
- 调用
execute()
方法执行 SQL 语句。
- 调用
-
获取结果:
- 调用
fetch()
或fetchAll()
方法获取查询结果。
- 调用
-
关闭连接:
- 当脚本结束时,PDO 自动关闭数据库连接。
(2) 数据流
-
写入数据:
- 开发者通过 SQL 语句向数据库写入数据。
-
读取数据:
- 数据库返回查询结果,PDO 将其转换为 PHP 数组或对象。
7. 总结
-
核心组成部分:
- PDO 类。
- PDOStatement 类。
- 异常处理。
- 驱动支持。
- 事务管理。
-
使用场景:
- 数据库连接。
- 预处理语句。
- 数据查询。
- 事务管理。
-
底层原理:
- 创建连接。
- 准备语句。
- 绑定参数。
- 执行查询。
- 获取结果。
- 关闭连接。
-
程序流和数据流:
- 写入数据:开发者通过 SQL 语句向数据库写入数据。
- 读取数据:数据库返回查询结果,PDO 将其转换为 PHP 数组或对象。