MySQL PDO Name-Value 仅使用最后一个参数的准备语句

MySQL PDO Name-Value Prepared Statement Using Last Parameter Only

如标​​题所示,我将 MySQL PDO 与准备好的语句一起使用,并且在执行时,我将单个值(最后提供的值)推送到所有字段中。

Table 看起来像这样:

INSERT 看起来像这样:

INSERT INTO my_table(a_id, b_id) 
VALUES (:a_id, :b_id)

要插入的代码如下所示...

$stmt = $conn->prepare($sql);

foreach($params as $k => $v) {
    $stmt->bindParam(
        $k,
        $v
    );
}

$stmt->execute();

该语句成功插入一个值(确认 $conn 存在、活动和打开,并且语句已设置且参数已绑定)。

我已经通过在 foreach 内部调试确认了这些值,在那里我得到了两个参数(在 $params 中)“:a_id” => 1, “ :b_id" => 9999...

不过我的记录是 ({new_id}, 9999, 9999)。*

这意味着它看到并使用“:b_id”=> 9999,但似乎删除或覆盖“:a_id”=> 1...

我认为下划线可能是个问题(但显然过去有几个人审查过源代码表明下划线没问题...虽然连字符不是)。

我没有重复使用参数(我的理解是每个准备好的语句允许使用一次)...

这里是否遗漏了一些命名参数问题?因为它基本上是 ->bindParam() 到 ->execute(),所以我没有太多的空间来解决问题。

我正在尝试解决使用 Fat Free Framework 时 ORM-based 数据访问的速度问题,但我认为那里没有干扰。

供参考,这是 运行 在 PHP 5.5.8 / Windows / IIS.

编辑:*

我可以确认移动到位置参数也在做同样的事情。

INSERT INTO my_table(a_id, b_id) 
VALUES (?, ?)

代码更改为...

$stmt = $conn->prepare($sql);

$i = 1;
foreach($params as $value) {
    $stmt->bindParam(
        $i,
        $value
    );
    $i++;
}

$stmt->execute();

阐明 $params 数组是如何设置的……事情被传递给这段代码(这是抽象数据库处理程序的核心),并且数组是手动构造的……

$results = \XX\DB::do_cmd(
    $db, 
    self::SQL_INSERT, 
    array(
        ':a_id' => intval($this->a_id),
        ':b_id' => intval($this->b_id),
    )
);

还有 ({new_id}, 9999, 9999)...

注意:为了消除混淆,除了进行基于位置的传递之外,我还对值进行了硬编码以查看我会得到什么...

$results = \XX\DB::do_cmd(
    $db, 
    self::SQL_INSERT, 
    array(
        1,
        1234,
    )
);

我的记录出来了({new_id}, 1234, 1234)。同样的问题,不同的值。

我感觉这里有一个 "gotcha"...但我不知道它是什么。

有趣的是,我根据这两个值(以防止重复)在 INSERT 之前仔细检查 table 是否存在现有记录,并且检查正确地识别出记录在那里...尽管它在数据库中是错误的...这意味着 SELECT 和 INSERT 正在对参数做同样的事情(尽管并不令人惊讶,因为参数处理是相同的)。

编辑 2:

更新说明已解决。使用...

$stmt->execute($params); // scrap the foreach nonsense...

bindValue() 而不是 bindParam() 也是合适的。

注意:我使用的是以下 PHP 文档 (http://php.net/manual/en/pdo.prepared-statements.php),它没有区分 bindValue() 与 bindParam()...

变量必须按引用调用:

$stmt = $conn->prepare($sql);

foreach($params as $k => &$v) {
    $stmt->bindParam(
        $k,
        $v
    );
}
$stmt->execute();

在此处查看第一条用户贡献的评论:

http://php.net/manual/en/pdostatement.bindparam.php

感谢大家的帮助!

我采用了 Michael 的解决方案,但也测试了 Ryan 的解决方案。

更新说明已解决。使用...

$stmt->execute($params); // scrap the foreach nonsense...

bindValue() 而不是 bindParam() 也是合适的。

最后,根据 Ryan 的评论,我将发布一个答案。

再次感谢!