PHP:在带有 SQL 注入预防的查询中使用 IN 语句时出错

PHP: Error when using IN statement in query with SQL injection prevention

我是 PHP 的新手,希望有人能帮助我。

我目前有以下 PHP,它是 jQuery 中 Ajax 调用的一部分。 当手动输入 ID 而不是 ?(例如 1,2,3,4,5)然后这按预期工作但是当我使用查询如下所示,只有 returns 一项如下所示,所以我相信 IN(?) 的组合和我防止 SQL 注入的尝试在这里不起作用。

谁能告诉我我做错了什么?
此外,这会创建一个多维数组,我想知道这是否可以简化,因为我只需要每个项目的 ID (tID) 和值 (content)。

我的PHP:

$content = implode(",", $_POST["content"]);  // an array containing IDs retrieved from Ajax
$languageFrm = $_POST["languageFrm"];

$stmt = $conn->prepare("SELECT tID, " . $languageFrm . " FROM TranslationsMain WHERE tID IN(?) ORDER BY tID");
$stmt->bind_param("s", $content);
$stmt->execute();
$result = $stmt->get_result();
while($arrTranslations = $result->fetch_assoc()){
    $translations[] = array("tID" => $arrTranslations["tID"], "content" => $arrTranslations[$languageFrm]);
}
var_dump($translations);

当前结果 Ajax:

array(1) {
  [0]=>
  array(2) {
    ["tID"]=>
    int(1)
    ["content"]=>
    string(6) "Value1"
  }
}

更新:
我的问题是,即使发布的链接和当前答案似乎指的是正确的解决方案,我也无法使 PHP 代码的其余部分正常工作,因为每当我使用建议的解决方案之一时,我都会收到错误消息“ Call to a member function fetch_assoc() on a non-object...".

非常感谢您对此的任何帮助,
麦克

您将字符串绑定到 SQL 代码中的单个参数。这意味着您的 SQL 转换为 SELECT something FROM table WHERE attribute IN ("1,2,3,4,5"),这显然不是您想要的。

您要做的是动态地将多个参数绑定到您的 SQL。这可以通过动态设置准备好的语句中的参数数量来实现,如 PHP manual under Example #5 of PDOStatement::execute() 中所示。我已将此作为一般示例添加到手册中,因为它是一个非常常见的用例。


由于您在这里使用的是 MySQLi 而不是 PDO,因此我将提供 MySQLi 等效示例...

$params = $_POST["content"];

$place_holders = implode(',', array_fill(0, count($params), '?'));


$stmt = $conn->prepare("SELECT tID, " . /* no way on earth will I ever do
                                           this $languageFrm */ null .
                       " FROM TranslationsMain WHERE tID IN($place_holders) ORDER BY tID");
// substitute PDO::execute() for call_user_func_array to bind_params because MySQLi sucks
call_user_func_array([$stmt, 'bind_param'], $params);
$stmt->execute();
$result = $stmt->get_result();
while($arrTranslations = $result->fetch_assoc()){
    $translations[] = array(
                            "tID" => $arrTranslations["tID"],
                            "content" => $arrTranslations[$languageFrm],
                           );
}
var_dump($translations);

您仍然容易受到 SQL 注入

还请考虑您准备好的语句 容易受到 SQL 注入 因为您不安全地将用户提供的输入直接连接到您的 SQL 语句来自$_POST["languageFrm"]

$stmt = $conn->prepare("SELECT tID, " . $languageFrm .
        " FROM TranslationsMain WHERE tID IN(?) ORDER BY tID");

你准备好的语句中那个大红色 $languageFRM 来自用户输入,是你的 SQL 代码的一部分,也就是说,你在查询中使用参数的所有努力在这里变得毫无用处。