Php MySQL PDO Name Value Prepared语句仅使用最后一个参数

Php MySQL PDO Name Value Prepared语句仅使用最后一个参数,php,pdo,mysqli,Php,Pdo,Mysqli,如标题所示,我使用MySQL PDO和一个准备好的语句,执行时,我得到一个值(最后提供的值)推送到所有字段中 表如下所示: id(整数-自动递增) a_id(int) b_id(int) INSERT如下所示: INSERT INTO my_table(a_id, b_id) VALUES (:a_id, :b_id) 要插入的代码如下所示 $stmt = $conn->prepare($sql); foreach($params as $k => $v) { $s

如标题所示,我使用MySQL PDO和一个准备好的语句,执行时,我得到一个值(最后提供的值)推送到所有字段中

表如下所示:

  • id(整数-自动递增)
  • a_id(int)
  • b_id(int)
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()to->execute(),所以没有太多的空间让我进行故障排除

我试图在使用无脂肪框架时解决基于ORM的数据访问的速度问题,但我不认为存在干扰

作为参考,这是在PHP5.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数组是如何设置的。。。这段代码(这是抽象数据库处理程序的核心)正在被传递,数组是手动构造的

i、 e

仍然得到({new_id},9999,9999)

注意:为了消除混淆,除了使用基于位置的传球外,我还硬编码了值,以查看得到的结果

$results = \XX\DB::do_cmd(
    $db, 
    self::SQL_INSERT, 
    array(
        1,
        1234,
    )
);
我的记录出来了({new_id},12341234)。同样的问题,不同的价值观

我觉得这里有一个“抓住你了”的感觉。。。但我不知道那是什么

有趣的是,在插入之前,我根据这两个值(防止重复)对表中的现有记录进行了双重检查,该检查正确地标识了该记录在那里。。。尽管数据库中有错误。。。这意味着SELECT和INSERT对参数的处理是相同的(尽管这并不奇怪,因为参数处理是相同的)

编辑2:

更新为已解决的注释。使用

$stmt->execute($params); // scrap the foreach nonsense...
$stmt->execute($params); // scrap the foreach nonsense...
bindValue()而不是bindParam()也是合适的


注意:我使用的是以下PHP文档(),它没有区分bindValue()和bindParam()…

变量必须通过引用调用:

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

foreach($params as $k => &$v) {
    $stmt->bindParam(
        $k,
        $v
    );
}
$stmt->execute();
请参见此处的第一条用户评论:


谢谢大家的帮助

我同意Michael的解决方案,但也测试了Ryan的

i、 e

更新为已解决的注释。使用

$stmt->execute($params); // scrap the foreach nonsense...
$stmt->execute($params); // scrap the foreach nonsense...
bindValue()而不是bindParam()也是合适的

总而言之,根据Ryan的评论,我正在推出一个答案


再次感谢

您可以发布设置
$params
的代码和定义
$sql
的代码吗?如果PDO正在模拟prepares(
ATTR\u EMULATE\u prepares
),则可以重用参数,这是MySQL的默认设置。此外,请发布
var\u dump($params)
,尽管您已经调试过它。您可以简化此操作以避免
bindParam()
,因为您没有指定类型。您可以只使用
$stmt->execute($params)
在“foreach”循环中使用“bindValue”而不是“bindParam”。否则,您只绑定到只有一个变量的变量“$v”!它的最后一个值是“9999”。@RyanVincent发现得很好。我可以确认RyanVincent和@MichaelBerkowski工作中提到的两个选项(即直接在$params上执行,并使用bindValue而不是BindParam)。谢谢我不知道如何在这里标记答案,但我很确定有人必须在评论之外发布一个答案…那是行不通的。。。它将与每个参数一起执行。。。如果我在做多个插入,我可能会在循环中执行->execute()。。。事实证明,这个循环在这种情况下是不必要的。对不起,我第一次看错了这个问题,就下结论了。我重新阅读并完全更改了我的答案。这与最初提出的答案不同,但你是对的,()确实引起了对通过引用传递的变量的注意;然而,我不应该强制执行,我不确定这在foreach中会起什么作用。我只知道&不能进入函数调用(5.3.0生成警告,5.4.0生成致命错误等):您确实看到&进入了循环的foreach部分,而不是函数调用,对吗?基本上,我的答案和Ryan的答案是一样的——他指出你将它绑定到单个变量$v,我正在解释如何克服这个问题。谢谢Peter!我明白你现在的目的。我想我已经看到它更普遍地通过“虚拟”变量来表达。。。(即my_func($k,$dummy=$v);键入thing…)特别是在实际的函数调用中,但是您正在获取对变量的引用,而不是本例中的变量,以纠正绑定问题。如果我还是很笨,你愿意继续,请放心,但我认为我们基本上都被涵盖了。谢谢你为我们发布了答案,我们都很乐意提供帮助。