循环遍历变量数组并使用 bind_param 插入

Looping through a variable array and inserting using bind_param

我正在尝试遍历多个数组以将数据插入 mysql 数据库。我试图绑定数据,以便我可以循环遍历它。可以有不同数量的数据绑定到的列。

似乎没有按预期处理数据 Im 绑定,插入最终失败。

我有一个列数组,用于存储列名和数据类型。我还有一个值数组,用于存储要插入的值。示例数据:

$colArr = array (
    array('i', 'ID'),
    array('s', 'Date')
);

$valArr = array(
    array(1, 'now()'),
    array(2, 'now()'),
);

//I create my type and query strings as well as the array referencing the columns for binding.

$valStrForQry = rtrim(str_repeat('?, ', count($v['colArr'])), ', '); //result: '?, ?'
$params = array();
$colsForQry = '';
$typeStr = '';
$cntr = 0;
foreach ($colArr as $cols) {
    $colsForQry .= $cols[1] . ', ';
    $typeStr .= $cols[0];
    $params[] = &$valArr[$cntr][1];
    $cntr++;
}

$colsForQry = rtrim($colsForQry, ', '); //result: 'ID, Date'

$qry = 'INSERT INTO table (' . $colsForQry . ') VALUES (' . $valStrForQry . ')';
$stmt = $mysqli->prepare($qry);

//Bind the parameters.

call_user_func_array(array($stmt, 'bind_param'), array_merge(array($typeStr), $params));

//Loop through the values array, assign them using eval, and execute the statement. Im open to suggestions if theres a better way to do this.

foreach ($valArr as $vals) {
    $cntr = 0;
    foreach ($colArr as $c) {
        eval('$' . $c[1] . ' = ' . $vals[$cntr] . ';');
        $cntr++;
    }

    if ($stmt->execute() === FALSE) {
        //show $stmt->error for this iteration
    } else {
        //show success for this iteration
    }
}

第一次迭代成功插入了不正确的数据。即插入的ID是0,不是1,没有插入其他信息。第二次迭代(以及所有连续迭代)导致以下错误消息:Duplicate entry '0' for key 'PRIMARY'

我在这里做错了什么,是评估还是其他什么?我不确定如何解决这个问题。

与其继续尝试使现有代码正常工作,不如建议使用 KISS 起点,不使用 prepare()eval()bind_param() .

  $cols = ['ID', 'Date'];
  $vals = [
    [1, '\'now()\''],
    [2, '\'now()\''],
  ];

  foreach ($vals as $val)
  {
    $sql = 'INSERT INTO table (' . implode($cols, ', ') . ') VALUES (' . implode($val, ', ') . ')';
    // exec here
  }

为了使这更安全一些,您可能希望在内爆之前转义所有值,或者 before/as 它们被放入您正在使用的数组中。恕我直言,现有的代码太过"clever" 无法做这么简单的事情。

或者,您可能需要考虑切换到使用 PDO 库而不是 mysqli。 PDO 支持在每个参数的基础上绑定命名参数,这可以在没有 eval() 的循环中完成。

其他人可能会得到提供的 "clever" 解决方案,而不是当然。