PHP PDO + 准备语句

5
$sql='SELECT phrase,english FROM static_site_language WHERE page=?;';
$pds=$database->pdo->prepare($sql); $pds->execute(array($_POST['languagepage']));

上述代码运行正常。然而我需要将另一个变量放入prepare语句中。我尝试了以下代码,但似乎不起作用:
$sql='SELECT phrase,? FROM static_site_language WHERE page=?;';
$pds=$database->pdo->prepare($sql); $pds->execute(array($_POST['language'],$_POST['languagepage']));

我知道 $_POST['language'](通过打印它)只包含单词“english”。

在这个 select 语句的这部分中,是否可以放置一个准备好的变量呢?

谢谢。


语法似乎没有错误,你收到了什么错误代码? - dotslashlu
没有错误 - 但是它只会给我英语这个词,而不是从数据库中返回值。这是变量的值和DB列的标题。 - Adam
{"free":"免费","meetsingles":"认识单身人士","searchprofiles":"搜索个人资料"} - Adam
2个回答

7
查询参数只能替代常量值,而不能替代列名。
在准备查询时必须指定所有的列和表,不能将选择列的步骤推迟到后续执行阶段。
如果要使用用户输入来确定列名,请使用“白名单映射”将用户输入限制为有效选项。映射数组的键是合法的用户输入,映射数组的值是您想在SQL查询中使用的字符串,即列名。
$lang_col_map = array(
  "DEFAULT" => "english",
  "en"      => "english",
  "es"      => "spanish"
);
$lang_col = $lang_col_map[ $_POST["language"] ] ?: $lang_col_map[ "DEFAULT" ];

$sql='SELECT phrase,$lang_col FROM static_site_language WHERE page=?;';
$pds=$database->pdo->prepare($sql); 
$pds->execute(array($_POST['languagepage']));

这样,您就可以确保仅 $lang_col_map 中的值可以成为 SQL 查询的一部分,并且如果用户尝试在 HTTP 请求中发送任何棘手的内容,则会被忽略,因为它不匹配该映射的任何键。 因此,查询免于 SQL 注入。
有关更多信息,请参见我的演示文稿SQL Injection Myths and Fallacies

按照设计,所有的问题/查询在被提出之前都应该是已知的。 - Xeoncross

2

预处理语句仅支持数据库支持的值参数。

在您的第二个语句中,第一个“?”是占位符,用于列名,而不是值。

您必须使用动态SQL语句。为此,您必须防止SQL注入。

$language_authorized = array('english', 'french', 'spanish');
$language = $_POST['language'];
if (in_array($language_authorized, $language)) {
  $sql='SELECT phrase,'.$language.' FROM static_site_language WHERE page=?;';
  $pds = $database->pdo->prepare($sql);
  $pds->execute(array($_POST['languagepage']));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接