php在foreach循环中使用预处理语句

时间:2016-04-21 18:34:27

标签: php mysqli

根据这个example准备好的语句我首先绑定参数,然后设置参数的值。

我们假设我有一个2-dim数组$别名

Preferences

为什么这段代码正常工作

$array1 = [
    'id' => 1,
    'tstamp' => 123456789,
    'alias' => '$alias',
];

$array2 = [
    'id' => 1,
    'tstamp' => 123456789,
    'alias' => '$alias2',

];

$alias = [$array1, $array2];

这不是吗?

$insert = 'INSERT INTO abcdef VALUES (?,?,?)';
$insertStmt = $conn->prepare($insert);
foreach ($alias as $array) {
    $insertStmt->bind_param('iis', $array['id'], $array['tstamp'], $array['alias']);
    $insertStmt->execute();
}

如果我必须一直绑定参数,那么会有更多的交通,不是吗?

3 个答案:

答案 0 :(得分:4)

bind_param()通过引用绑定到特定的zval container。在循环的每次迭代中,都会为其新的数组符号表分配自己的zval容器。如果在绑定时zval容器不存在,则将创建它们。可以用以下代码显示:

$insertStmt = $conn->prepare('INSERT INTO abcdef VALUES (?,?,?)');
$insertStmt->bind_param('sss', $array['id'], $array['tstamp'], $array['alias']);
var_dump($array);

输出:

array (size=3)
  'id' => null
  'tstamp' => null
  'alias' => null

即使我们没有在任何地方声明$array,该绑定也会使用空值隐式创建它。绑定将继续指向该空数组。

当然,当我们开始迭代别名数组时,每次都会重新创建$array。我们绑定了参数的旧数组符号表现在不见了。我们尚未将任何内容绑定到新数组。

要解决此问题,您只需将bind_param()循环内的foreach移动为:

$insertStmt = $conn->prepare('INSERT INTO abcdef VALUES (?,?,?)');
foreach ($alias as $array) {
    // bind to the new zval containers every iteration
    $insertStmt->bind_param('sss', $array['id'], $array['tstamp'], $array['alias']);
    $insertStmt->execute();
}

答案 1 :(得分:4)

  

如果我必须始终绑定参数,那么还有更多   交通,不是吗?

流量是根据prepareexecute事件生成的。

话虽如此,您可以重新安排一点以将->bind_param()移到循环外。更简单的方法是绑定变量而不是数组:

$array1 = ['id' => 1, 'tstamp' => 123456789, 'alias' => '$array1'];
$array2 = ['id' => 1, 'tstamp' => 123456789, 'alias' => '$array2'];
$arrays = [$array1, $array2];

$insert = 'INSERT INTO abcdef VALUES (?,?,?)';
$insertStmt = $conn->prepare($insert);

$bv_id      = NULL;
$bv_tstamp  = NULL;
$bv_alias   = NULL;
$insertStmt->bind_param('iis', $bv_id, $bv_tstamp, $bv_alias);

foreach ($arrays as $array) {
    // you could use extract($array, ...) below
    // but its use is highly discouraged
    $bv_id     = $array['id'];
    $bv_tstamp = $array['tstamp'];
    $bv_alias  = $array['alias'];
    $insertStmt->execute();
}

如果必须使用数组,请使用以下方法:

$array = ['id' => null, 'tstamp' => null, 'alias' => null];
$insertStmt->bind_param('iis', $array['id'], $array['tstamp'], $array['alias']);
foreach ($arrays as $copy) {
    foreach ($copy as $k => $v) {
        $array[$k] = $v;
    }
    $insertStmt->execute();
}

请注意,我在foreach构造中为循环变量使用了不同的名称(我们需要跟踪绑定到该语句的数组,并且循环变量在每次迭代时都会被覆盖)。您将必须手动将值从循环变量复制到绑定数组。

答案 2 :(得分:-1)

以您的情况

此代码有效

$insert = 'INSERT INTO abcdef VALUES (?,?,?)';
$insertStmt = $conn->prepare($insert);
foreach ($alias as $array) {
    $insertStmt->bind_param('iis', $array['id'], $array['tstamp'], $array['alias']);
    $insertStmt->execute();
}

由于数组迭代,我们使用for循环或foreach提取键数组中的键值,因此在$ array变量中的此代码值将从$ alias数组中设置一个值

在此代码中

$insert = 'INSERT INTO abcdef VALUES (?,?,?)';
$insertStmt = $conn->prepare($insert);
$insertStmt->bind_param('iis', $array['id'], $array['tstamp'], $array['alias']);
foreach ($alias as $array) {
   $insertStmt->execute();
}

您使用了$ array变量,该变量未在任何上限区域中初始化或声明,因此它将获得空值,因此每次execute函数将获得空值。...