我开始知道使用 MySQLi 和 PDO 时准备好的语句是如何工作的,第一步,我启用了 MySQL 查询监控,如下所述:如何查看实时 MySQL 查询?. 然后我创建了以下测试:
使用 mysqli:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) {
$stmt->bind_param("i", $user);
$user = "''1''";
服务器日志:
130802 23:39:39 175 Connect ****@localhost on testdb 175 Prepare SELECT * FROM users WHERE username =? 175 Execute SELECT * FROM users WHERE username =0 175 Quit
使用 PDO:
$user = "''1''";
$sql = 'SELECT * FROM user WHERE uid =?';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->bindParam(1, $user, PDO::PARAM_INT);
服务器日志:
130802 23:41:42 176 Connect ****@localhost on testdb 176 Query SELECT * FROM user WHERE uid ='\'\'1\'\'' 176 Quit
但是,两者都提供相同的结果:
uid: 0
username: admin
role: admin
注意:uid = 0
是正确的,因为intval("''1''") = 0
这里重要的是:
PDO 查询如何在向 MySQL 发送不同的查询时获得相同的结果?
SELECT * FROM user WHERE uid ='\'\'1\'\''
我从 PHP 手册中只找到一个指示:http ://www.php.net/manual/en/pdo.prepare.php
笔记:
模拟的预处理语句不与数据库服务器通信,因此 PDO::prepare() 不检查语句。
但我不确定 MySQL 如何处理此查询并替换'\'\'1\'\''
为0
. 在这种情况下,如果使用 PDO,监视查询将不准确,同时,使用 PDO 更好地了解发送到 MySQL 而不是 MySQLi 的确切查询。
更新: 将参数类型frm整数更改为字符串后:
MySQLi 日志:
188 Prepare SELECT * FROM awa_user WHERE username =? 188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\'' 188 Quit
PDO 日志:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\'' 189 Quit
这意味着 MySQLi 和 PDO 在使用字符串时会在发送到 MySQL 之前转义数据,而对于整数,mysqli 在发送查询之前应用 intval() 或类似的东西,比尔也回答了这是正确的。