提问者:小点点

如何在MySQL语句中包含PHP变量


我正在尝试在contents表中插入值。 如果我的值中没有PHP变量,它可以正常工作。 当我将变量$type放入values中时,这就不起作用了。 我做错了什么?

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) 
     VALUES($type, 'john', 'whatever')");

共3个答案

匿名用户

在任何MySQL语句中添加PHP变量的规则非常简单明了:

  1. 任何表示SQL数据文本(或者,简单地说,SQL字符串或数字)的变量都必须通过准备好的语句添加。 没有例外。
  2. 任何其他查询部分(如SQL关键字,表或字段名或运算符)都必须通过白名单筛选。

所以,由于您的示例只涉及数据文本,那么所有变量都必须通过占位符(也称为参数)添加。 要执行此操作:

  • 在SQL语句中,用占位符替换所有变量
  • 准备结果查询
  • 将变量绑定到占位符
  • 执行查询

下面是如何使用所有流行的PHP数据库驱动程序来实现此操作:

这样的驱动程序不存在。

$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description) 
             VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();

代码有点复杂,但是所有这些操作符的详细解释可以在我的文章中找到,如何使用Mysqli运行插入查询,以及一个大大简化该过程的解决方案。

$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description) 
             VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);

在PDO中,我们可以将绑定和执行部分组合在一起,这是非常方便的。 PDO还支持命名占位符,有些人觉得这非常方便。

但有时我们添加了一个变量,它表示查询的另一部分,如关键字或标识符(数据库,表或字段名)。 在这种情况下,必须对照脚本中显式写入的值列表检查变量。 在我的另一篇文章中解释了这一点,根据用户的选择在ORDER BY子句中添加一个字段名:

不幸的是,PDO没有标识符(表名和字段名)的占位符,因此开发人员必须手动过滤它们。 这种过滤器通常被称为“白名单”(我们只列出允许的值),而不是“黑名单”(我们列出不允许的值)。

所以我们必须在PHP代码中显式地列出所有可能的变体,然后从中进行选择。

下面是一个例子:

$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) { 
    throw new InvalidArgumentException("Invalid field name"); 
}

完全相同的方法应该用于方向,

$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) { 
    throw new InvalidArgumentException("Invalid ORDER BY direction"); 
}

在这样的代码之后,可以安全地将$direction$orderby变量放入SQL查询中,因为它们要么等于允许的变量之一,要么会引发错误。

关于标识符,最后要提到的是,它们还必须根据特定的数据库语法进行格式化。 对于MySQL,标识符周围应该是backtick字符。 因此,我们的order by示例的最终查询字符串将是

$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";

匿名用户

为了避免SQL注入,insert语句带有be

$type = 'testing';
$name = 'john';
$description = 'whatever';

$stmt = $con->prepare("INSERT INTO contents (type, reporter, description) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $type , $name, $description);
$stmt->execute();

匿名用户

最好的选择是准备好的陈述。 在引语和转义上瞎折腾是一件很难开始的工作,也很难维持。 迟早你会不小心忘记引用一些东西,或者两次转义同一个字符串,或者搞砸类似的事情。 你可能要好几年才能发现这些虫子。

http://php.net/manual/en/pdo.prepared-statements.php

相关问题