在构造 SQL 删除语句时,很多开发者容易直接拼接字符串,比如这样:
$id = $_GET['id'];
$sql = "DELETE FROM users WHERE id = $id";
这种方式极易受到 SQL 注入攻击。例如,恶意用户传入 1 OR 1=1,就会删除整张表的内容。
使用 PDO 的预处理语句,则可以彻底避免这个问题。它通过将 SQL 和数据分离的方式,确保传入的数据不会被解释为 SQL 语句的一部分。
下面是一个使用 PDO 删除用户记录的安全方式:
<?php
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$username = 'root';
$password = 'your_password';
try {
$pdo = new PDO($dsn, $username, $password);
// 设置错误模式为异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 预处理语句
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
// 绑定参数并执行
$id = 5; // 例如从表单或 URL 获取的用户ID
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount()) {
echo "记录已成功删除。";
} else {
echo "未找到匹配的记录。";
}
} catch (PDOException $e) {
echo "数据库错误: " . $e->getMessage();
}
?>
在这个例子中,我们使用了 :id 占位符,并通过 bindParam 绑定变量,确保数据类型一致性。
有时删除条件不止一个,例如删除某个用户在特定时间的登录记录:
<?php
$stmt = $pdo->prepare("DELETE FROM login_logs WHERE user_id = :user_id AND login_time < :before_time");
$user_id = 3;
$before_time = '2024-01-01 00:00:00';
$stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
$stmt->bindParam(':before_time', $before_time);
$stmt->execute();
如果删除条件是动态生成的,比如来自前端的复选框批量删除,可以这样构造:
<?php
$ids = [2, 5, 7]; // 来自表单或前端的 ID 列表
// 构造带有占位符的 SQL
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$sql = "DELETE FROM users WHERE id IN ($placeholders)";
$stmt = $pdo->prepare($sql);
// 执行语句,绑定所有参数
$stmt->execute($ids);
这种方式利用了 ? 占位符和 execute 传入数组的能力,既安全又灵活。
永远不要将用户输入直接拼接进 SQL 中。
使用绑定参数时,指定数据类型(如 PDO::PARAM_INT)可提高安全性与性能。
在删除之前可以先进行 SELECT 检查,确认操作对象是否存在。
使用事务处理(beginTransaction() / commit())以避免意外删除。
如果你想基于 HTTP 请求删除某条记录,例如通过接口 https://m66.net/api/delete_user.php?id=9,你可以这样写:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id'])) {
$id = (int) $_GET['id'];
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
echo json_encode([
'success' => true,
'message' => '用户删除成功',
]);
} else {
http_response_code(400);
echo json_encode([
'success' => false,
'message' => '请求不合法',
]);
}
?>
接口设计中同样必须重视输入验证和参数绑定,防止通过 API 的方式被攻击。
相关标签:
PDOStatement