如何在PHP中将变量传递给MySQL查询?

时间:2012-09-14 12:09:36

标签: php mysql

我有以下MySQL命令试图获取用户的登录信息:

$requete = "SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'";
echo ("$requete");

它不起作用。问题是,在执行此代码时,我看到以下输出(而不是执行查询的结果):

SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'

在PHP中将变量传递给MySQL查询的正确方法是什么?

1 个答案:

答案 0 :(得分:10)

在PHP中,与许多其他编程语言一样,=运算符assigns左侧操作数变量的右侧操作数的值。也就是说,执行这样的命令后,=符号左侧的变量将包含=符号右侧表达式的值。

你的右手操作数是double-quoted string literal,其中PHP用它们的值扩展(替换)变量;但是,结果(分配给左侧操作数)只是一个字符序列。

PHP的echo构造将其参数转换为字符串(s),按顺序连接它们并将结果发送到输出缓冲区。

在你的情况下,唯一的参数是另一个双引号字符串文字"$requete",其中PHP再次使用它们的值扩展变量:这次文字的内容只是变量$requete,因此引用它只会导致多余的解析开销;并且由于该变量被赋予了前一个字符串文字,因此结果字符串(由echo输出)等于原始字符串文字。因此,您的两个陈述具有与以下相同的效果:

echo "SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'";

PHP尚未被告知存在RDBMS,这是您希望由该RDBMS评估的SQL,或者您希望输出生成的结果集。

更糟糕的是,除非您绝对确定 $login$pass不包含未转义的'字符,否则可能会导致解析该字符串的SQL意外行为。攻击者经常利用这种疏忽来执行SQL injection attacks,这可能会危及整个数据库。 最安全避免这种情况的方法是从不来评估SQL的变量,而是使用prepared statements将变量作为参数传递给它。

我建议您查看PHP Data Objects,这样可以非常轻松地访问安全数据库:

$dbh = new PDO("mysql:dbname=$dbname;charset=utf8", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$qry = $dbh->prepare('
  SELECT login, pass
  FROM   membres
  WHERE  login = ? AND pass = ?
');

$qry->execute(array($login, $pass));
while ($row = $qry->fetch(PDO::FETCH_ASSOC)) print_r($row);

然而,有些事情需要注意:

  1. 您只是从匹配常量值的数据库字段中进行选择,这是毫无意义的:从这样的查询中可以获得的唯一信息是数据库中匹配记录的数量,但是资源被浪费在返回多余的数据。

    您可以改为SELECT COUNT(*) FROM membres WHERE ...获取相同的信息,而不会浪费任何开销;或者如果您只想发现是否有一个或多个匹配记录,SELECT EXISTS (SELECT * FROM membres WHERE ...)会更有效率。

  2. 您似乎正在创建一个登录脚本,这可以通过安全的方式完成:如果您有兴趣了解更多内容,请阅读The Definitive Guide To Forms based Website Authentication。那里有图书馆和工具,你可以直接进入你的项目,以避免浪费资源重新发明轮子(以及其他人学到的许多痛苦的错误)。