【问题标题】:Binding an array in MySQLi prepared Insert statement PHP [duplicate]在MySQLi准备的插入语句PHP中绑定数组[重复]
【发布时间】:2020-09-30 17:46:11
【问题描述】:

我尝试了多种方法来创建一个函数来将动态数组值绑定到 MySQLi 准备好的语句中。但我收到错误“未捕获的 mysqli_sql_exception:未为准备好的语句中的参数提供数据”

这是我的代码:

if (count($fields) == count($values)) {
    $fielddata = implode(", ", $fields);
    $questions = rtrim(str_repeat("?, ", count($values)), ", ");
    $typedata = implode("", $type);

    foreach ($values as $index => $current_val){ // build type string and parameters
        $value .= '$values['.$index.'],';
    }
    $value = rtrim($value,',');

    $statement = "INSERT INTO ".$table." (".$fielddata.") VALUES (".$questions.")";
    $stmt = $db->prepare($statement);
    $stmt->bind_param("sss", $value);

    $stmt->execute();
    $stmt->close();
    echo "inserted";
}

当我替换时相同的代码工作

$stmt->bind_param("sss", $value);

$stmt->bind_param("sss",$values[0],$values[1],$values[2]);
        

【问题讨论】:

  • 绑定循环内的值,而不是连接变量。
  • 由于此代码旨在用于插入具有相同数量值的可变数量的列,因此"sss" 部分肯定也需要动态创建
  • @olibiaz 这是mysqli_*,而不是PDO。我对mysqli不是很熟悉,但据我所知,它不支持这个

标签: php mysqli prepared-statement bindparam


【解决方案1】:

bind_param() 不接受由逗号分隔的值列表组成的字符串,这似乎是您试图传递的内容。

将您的 foreach 循环移到 prepare() 下方并绑定循环内的值。

if (count($fields) == count($values)) {
    $fielddata = implode(", ", $fields);
    $questions = rtrim(str_repeat("?, ", count($values)), ", ");
    $typedata = implode("", $type);

    //NOTE: You should verify that `$table` contains a valid table name.
    $statement = "INSERT INTO {$table} ({$fielddata}) VALUES ({$questions})";
    $stmt = $db->prepare($statement);
    
    //bind parameters using variable unpacking (PHP 5.6+), assuming `$typedata` actually contains the proper types.
    $stmt->bind_param($typedata, ...$values);
    
    $stmt->execute();
    $stmt->close();
    echo "inserted";
}

【讨论】:

    【解决方案2】:

    您似乎在bind_param() 中绑定了一个字符串作为第二个参数。此方法通过引用获取多个变量并将它们绑定到查询中的占位符,并且由于您绑定了单个字符串,因此绑定参数的数量不匹配。

    您需要将值存储在一个数组中,然后使用splat operator 解压它们。

    if (count($fields) == count($values)) {
        $fielddata = implode(", ", $fields);
        $questions = rtrim(str_repeat("?, ", count($values)), ", ");
    
        $statement = "INSERT INTO ".$table." (".$fielddata.") VALUES (".$questions.")";
        $stmt = $db->prepare($statement);
        $stmt->bind_param(str_repeat("s", count($values)), ...$values);
        $stmt->execute();
    }
    

    此外,类型应该是一个字母列表,表示每个被绑定的变量的类型。最好的情况是将它们全部绑定为字符串,因此只需对每个绑定变量重复 s

    注意 SQL 注入。您需要确保将字段名称正确列入白名单。如果这些值可以是任意值,则您可能容易受到 SQL 注入的攻击。

    【讨论】:

    • $values 字段前面的三个点实际上是做什么的?
    • @lock 这是一个 Splat 运算符。它解包变量,因此它们都单独传递给函数。
    猜你喜欢
    • 2013-11-09
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 2015-03-01
    • 1970-01-01
    相关资源
    最近更新 更多