PHP PDO +准备声明

时间:2011-12-30 02:55:40

标签: php pdo

$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'](来自打印)只包含“英语”这个词。 是否可以在select的这一部分中放置一个prepare变量?

THX

2 个答案:

答案 0 :(得分:7)

查询参数只能取代常量值 - 而不是列名。

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

如果希望用户输入确定列名称,请使用白名单地图将用户输入限制为有效选项。地图数组的键是合法用户输入。 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 Injection Myths and Fallacies

答案 1 :(得分:2)

Prepared语句仅支持数据库支持的参数。

在你的第二个声明中,第一个“?”是列名的占位符,而不是值。

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