PDO 使用 foreach 绑定 n 次相同的值

Posted

技术标签:

【中文标题】PDO 使用 foreach 绑定 n 次相同的值【英文标题】:PDO binds n times same value with foreach 【发布时间】:2013-08-18 17:45:56 【问题描述】:

我在 php 中有函数,它应该在 mysql IN 语句中绑定这么多变量,即在数组中。 我的问题是变量和键正在改变,但函数只绑定最后一个值 n 次。

我不知道问题出在哪里......

这是我的类方法:

public function getOtListByOtNumbers($conditions)
        $data_array = $conditions[SEARCH_OT];
    # To find last key (remove coma)
        $quantity = count($data_array);
        $marks = '';
    # Bind name string && rewriting value as integer
        foreach ($data_array as $key => $value)
            $i = $key+1;
            if ($i == $quantity)
                $marks .= ':key'.$i;
            
            else 
                $marks .= ':key'.$i.', ';
            
        
    # Query
        $sql="
        SELECT
            c_int_id,
            c_ot,
            c_tickets_amount,
            c_basket_value,
            c_person,
            c_company,
            c_city,
            c_package_number,
            c_delivery_method,
            c_ot_date,
            c_email,
            c_phone,
            c_comment,
            c_send
        FROM ws_orders
        WHERE c_ot IN (".$marks.")
        ORDER BY c_int_id DESC
        LIMIT :first, :last ";
        $stmt = $this->PDO->prepare($sql);

    # Bind n values
    // Here is a problem
        var_dump($data_array); // var dump 1
         foreach ($data_array as $key => $param)
            $key_number = $key +1;
            $key_name = 'key'.$key_number;
            $stmt->bindParam($key_name, $param, PDO::PARAM_INT);
            var_dump($key_name); // var dump 2
            var_dump($param); // var dump 3
        

    # Bind limit values
        $stmt->bindParam('first', $conditions[OT_SEARCH_FIRST_ROW], PDO::PARAM_INT);
        $stmt->bindParam('last', $conditions[OT_SEARCH_ROW_LIMIT], PDO::PARAM_INT);

    # If executed return result
        if ($stmt->execute() != FALSE) 
            $stmt_result = $stmt->fetchAll();
            $stmt->closeCursor();
            var_dump($stmt_result); // var dump 4

    # If not executed print debug and return FALSE
         else 
            var_dump($stmt->errorInfo());
            $this->debugQuery($stmt);
            $stmt_result = FALSE;
        

        return $stmt_result;
    

这里是 var dupms:

var 转储 1

array (size=2)
 0 => string '2761531'
 1 => string '2760650'

var 转储 2 & 3

string 'key1' (length=4)

string '2761531'

string 'key2' (length=4)

string '2760650'

来自该执行的 SQL 查询

        SELECT
            c_int_id,
            c_ot,
            c_tickets_amount,
            c_basket_value,
            c_person,
            c_company,
            c_city,
            c_package_number,
            c_delivery_method,
            c_ot_date,
            c_email,
            c_phone,
            c_comment,
            c_send
        FROM ws_orders
        WHERE c_ot IN ('2760650', '2760650')
        ORDER BY c_int_id DESC
        LIMIT 0, 30

那么我做错了什么?

编辑




所以我做到了;) 问题出在 foreach 上

代替:

     foreach ($data_array as $key => $param)
        $key_number = $key +1;
        $key_name = 'key'.$key_number;
        $stmt->bindParam($key_name, $param, PDO::PARAM_INT);
        var_dump($key_name); // var dump 2
        var_dump($param); // var dump 3
    

我给:

        for ($key_number = 0; $key_number < $quantity + 1; $key_number++) 
            $key_name = 'key'.$key_number;
            $stmt->bindParam($key_name, $data_array[$key_number], PDO::PARAM_INT);
        

它有效,但我仍然不知道早期的 foreach 有什么问题......

【问题讨论】:

太好了,你让它工作了!你应该回答这个问题并自己接受。这是“关闭”问题的推荐方式。 我的代表少于 10 个,所以我不能在 8 小时之前完成 :) 也许有人会描述为什么 foreach 不起作用 帮了一点忙 :-) 不知道foreach——当我看到这个问题时,我想,$conditions 一定有一些东西,也许它不完全包含有什么预期的。不过,现在没有时间 - sry $conditions 是多维数组,但我只使用了一个子数组,该数组的内容列在 var dump 1 中。每个循环中的数据都在变化(var dump 2 & 3 列表),但 bindParam 看不到它 【参考方案1】:

PDO::bindParam()PDO::bindValue() 之间存在区别。 PDO::bindParam 绑定参考,而不是值。当 foreach 进程结束时,$param 将引用最后一个数组值。在execute 调用时,所有绑定的引用都将被评估为相同的值。

官方PDO::bindParam 文档说:

与 PDOStatement::bindValue() 不同,变量被绑定为引用 并且只会在 PDOStatement::execute() 被评估时 调用。

如果您想在foreach 中绑定值,请使用PDO::bindValue

【讨论】:

【参考方案2】:

如果您将变量作为引用传递,它将对值起作用,但对键不起作用。

示例:

foreach ($data_array as $key => &$param) 
    $key_number = $key + 1; //this won't work
    $key_name   = 'key' . $key_number;
    $stmt->bindParam($key_name, $param, PDO::PARAM_INT);
    var_dump($key_name);    // var dump 2
    var_dump($param);       // var dump 3

【讨论】:

【参考方案3】:

问题在于 BindParam 通过引用传递第二个值。 PHP 重用(或在这种情况下似乎)$param 的地址,而不是实际值。 您的 foreach 可以使用:

$stmt->bindParam($key, $data_array[$key]);

这具有将数组的地址位置绑定在那个关键位置的效果,所以当你的sql执行时,它会得到正确的值。

你可能想要:

$stmt->bindValue($key, $param);

应该在 foreach 循环中而不是在执行语句中求值,并且是传递的值而不是地址位置。

【讨论】:

以上是关于PDO 使用 foreach 绑定 n 次相同的值的主要内容,如果未能解决你的问题,请参考以下文章

PDO - 对多个 foreach 循环使用相同的查询

使用 foreach 获取时覆盖 PDO 的 fetch()

PHP MySQL PDO 绑定输入/输出相同参数

在 foreach 循环中绑定数组值时,IMSSP“尝试绑定参数号 0”错误

PDO 两次插入相同的数据

使用 PHP PDO 显示 bindParam 的值