了解PDO准备语句和绑定参数

时间:2016-05-09 19:08:19

标签: php mysql pdo prepare bindparam

根据经验并且不断被告知使用预准备语句和绑定我的参数的好处,我在我的代码中经常使用这两种技术,但是我想完全理解这两种技术的目的:< / p>

根据我对准备好的陈述的理解:

$sql = "SELECT * FROM myTable WHERE id = ".$id;
$stmt = $conn->prepare($sql);
$stmt->execute();

前面的代码应该使用我提出的查询在数据库中创建一种缓冲区。现在从我的理解(我可能非常错误),以前的代码是不安全的,因为字符串$sql可能是任何东西,取决于$id实际是什么,如果$id = 1; DROP TABLE myTable;--,即使我有准备好的声明,我也会插入恶意查询。

从我的理解这是绑定我的参数com的地方。如果我改为:

$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();

数据库应该事先知道sql语句的所有部分: SELECT这些列* FROM myTableWHERE id =&#34;用户输入的变量&#34;以及"a variable that was input by the user" != a variable的查询失败。

有些人告诉我,我的理解是正确的,而其他人认为这是错误的,如果我错了,纠正或遗漏了某些东西,有人可以告诉我吗?并且根据您的需要精心制作,非常感谢所有反馈!

1 个答案:

答案 0 :(得分:2)

你纠正第一种情况是不安全的。但是,了解一下,如果您使用用户提供的数据和/或重复执行相同的查询,那么准备语句只会有价值,这一点非常重要。如果您正在执行没有变量的普通语句,您可以这样做:

$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);

并最终得到一个PDOStatement对象,就像使用PDO::exec()时一样。

对于你的第二个案例,再次,你在很大程度上是正确的。发生的事情是传递给数据库的变量被转义和引用(除非您使用第三个参数指定PDOStatement::bindParam(),否则它将作为字符串发送,对大多数情况来说都很好。)因此,查询赢了&#34;失败&#34;如果发送了错误的数据。它的行为就像您传递了一个在数据库中没有作为ID存在的有效数字一样。当然,some edge cases即使有正确准备的陈述,你仍然很脆弱。

此外,为了让生活更轻松,您可以使用这样的预准备语句进行隐式绑定:

$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);

或者甚至是这样,使用未命名的参数:

$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);

当然,在我输入答案时,大部分内容已在评论中解释过了!