PDO(PHP Data Objects)是 PHP 用于访问数据库的现代、数据库无关的接口。其最重要的功能是预编译语句,可防止 SQL 注入——这是任何数据库代码的关键安全实践。
使用 PDO 连接
= (
,
, ,
[
PDO:: => PDO::, // exceptions on errors
PDO:: => PDO::, // fetch rows associative arrays
]
);
PDO 使用相同的 API 跨数据库工作(MySQL、PostgreSQL、SQLite 等)。设置 ERRMODE_EXCEPTION 使数据库错误抛出可捕获的异常。
// ❌ NEVER do this — concatenating user input → SQL INJECTION vulnerability
$result = $pdo->query("SELECT * FROM users WHERE id = " . $_GET['id']);
// input "1 OR 1=1" or "1; DROP TABLE users" → disaster
// ✅ ALWAYS use prepared statements with bound parameters
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ? AND active = ?");
$stmt->execute([$_GET['id'], true]); // parameters bound SAFELY
$user = $stmt->fetch();
// named parameters work too
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(["email" => $email]);
预编译语句将 SQL 和数据分开发送——数据库将参数视为纯数据,从不作为可执行的 SQL。这使得注入不可能发生,无论用户输入什么。对于任何涉及用户输入的查询,这是不可商量的。
$stmt->fetch(); // one row (associative array)
$stmt->fetchAll(); // all rows
$stmt->fetchColumn(); // a single value
// INSERT/UPDATE/DELETE — also use prepared statements
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->execute([$name, $email]);
$pdo->lastInsertId(); // the new row's ID
$pdo->beginTransaction();
try {
$pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?")->execute([$amt, $from]);
$pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?")->execute([$amt, $to]);
$pdo->commit(); // all-or-nothing
} catch (Throwable $e) {
$pdo->rollBack(); // undo on failure
}
安全的数据库访问是 PHP 开发中最具安全性的方面之一,使用预编译语句的 PDO 是每个 PHP 开发者必须掌握的基本实践。
SQL 注入——由直接将不受信任的用户输入连接到 SQL 查询中引起——是最常见和最具破坏性的网络漏洞之一(允许攻击者读取、修改或销毁数据),但它完全可以被防止。预编译语句与绑定参数是解决方案:通过分别发送 SQL 结构和数据,数据库将用户输入视为永远无法作为 SQL 执行的纯数据,使得注入无论输入如何都不可能发生。
理解您必须始终对任何涉及用户输入的查询使用预编译语句(从不使用字符串连接)是不可商量的、安全至关重要的知识。
除了安全性外,PDO 的数据库无关接口、基于异常的错误处理、灵活的结果获取和事务支持使其成为在 PHP 中访问数据库的强大、现代方式。
由于数据库访问是大多数应用程序的基础,且 SQL 注入既常见又具有灾难性,掌握 PDO 和对预编译语句的绝对纪律是 PHP 开发者必须理解的最重要事情之一——这是安全应用程序和容易受到已知严重攻击的应用程序之间的区别。(Laravel 等框架在其下使用带有安全查询生成器/ORM 的 PDO,但基本原理保持不变。)