PDO binds n times same value with foreach

白昼怎懂夜的黑 提交于 2019-12-02 09:22:24

问题


I have function in PHP, which should bind in MySQL IN statement so many variables, that is in array. My problem is that variable and key is changing but function bind only last value n times.

I don't have idea where is the problem...

Here is my class method:

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;
    }

Here are var dupms:

var dump 1

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

var dump 2 & 3

string 'key1' (length=4)

string '2761531'

string 'key2' (length=4)

string '2760650'

SQL query from this execution

        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

So what I am doing wrong?

EDIT




So i did it ;) The problem was with foreach

Instead of:

     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
    }

I give:

        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);
        }

And it works, but i still don't know what the problem was with earlier foreach...


回答1:


There is the difference between PDO::bindParam() and PDO::bindValue(). PDO::bindParam binds reference, not value. When foreach process ends, $param will reference to the last array value. In the time of execute call all binded references will be evaluated to same value.

Official PDO::bindParam documentation says:

Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.

If you want bind values in foreach use PDO::bindValue.




回答2:


If you pass the variable as reference it would work fine for value, but won't work for key.

Example:

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:


The problem is that BindParam Passes the second value by reference. PHP reuses (or appears to in this case) the address of the $param, and not the actual value. Your foreach could have used:

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

This has the effect of binding the address location of the array at that key location, so when your sql executes, it gets the right value.

You probably wanted:

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

which should evaluate in the foreach loop instead of at the execute statement, and is a passed value instead of an address location.



来源:https://stackoverflow.com/questions/18271284/pdo-binds-n-times-same-value-with-foreach

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!