PHP PDO + Prepare Statement


PHP PDO + Prepare Statement

$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'。是否有可能把一个准备变量在选择的这一部分?

thx

查询参数只能代替常量值,不能代替列名。

所有列和表必须在准备查询时命名,不能将选择列推迟到后续执行步骤。

当您希望用户输入确定列名时,使用Whitelist Map将用户输入限制为有效的选择。map数组的键是合法的用户输入。map数组的值是要在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注入神话和谬误了解更多信息。

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

在第二个语句中,第一个"?"是列名的占位符,而不是值。

您必须使用动态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']));
}