简体   繁体   中英

PHP PDO - Using an array for a SELECT SQL Statement

I'm having a bit of an issue. Basically what I am trying to do is the following;

  • I am using PDO
  • I want the ability to pass an array containing the column name in the db (the key) and the info I want to insert (value). The array may contain 1, or many fields that need to be updated.
  • I have designed a function that looks like this:

Sample Array being passed:

$columnsToRetrieve = array('column1' => 'info', 
                            'column2' => 'data', 
                            'column3' => 'data');

And a sample function (did not include the DB initialization part)

function updateInfo ($columnsToRetrieve, $whereClauseValue) {

    $counter = 1;
    $queryString = 'UPDATE table SET ';
    foreach ($columnsToRetrieve as $k => $V) {
        $queryString .= $k . ' = ?';    
    }
    $queryString .= 'WHERE column4 = ?'
    $stmt = $dbc->dbConnection->prepare($queryString);
    foreach ($columnsToRetrieve as $k => $v) {
        $stmt->bindParam($counter, $v);
        $counter++;
    }
    $stmt->bindParam($counter, $whereClauseValue);
    $stmt->execute();
}

The problem is with the second foreach, where I am trying to use the bindParam($counter, $value). Although the right number and value populates, it doesn't seem to want to accept it.

Does anyone have any ideas how this can be done, or what I'm doing wrong above?

After debugging your code I see two issues:

  1. missing semicolon after $queryString .= 'WHERE column4 = ?' part.
  2. If I dump your resulting query, it would be something like

UPDATE table SET column1 = ?column2 = ?column3 = ?WHERE column4 = ?

see missing spaces. So what if you modify this line:

$queryString .= $k . ' = ?';

to

$queryString .= $k . ' = ?,';

and (in order to strip the last comma)

 $queryString .= ' WHERE column4 = ?'

replace with

$queryString = substr($queryString,0,-1) .  ' WHERE column4 = ?';

95% sure that your issue is your use of bindParam . bindParam works by reference, not by value. As a result your foreach loop isn't binding your values to your query, but rather the $v variable. By the time you call execute all parameters are bound to the same $v variable, so when you execute your query does not behave as expected.

The solution is simple: use bindValue() or execute() . Personally, I use execute() exclusively: it is simple to understand and read. Without a doubt though, the reference nature of bindParam() will cause plenty of trouble: I've been burned by it before.

Edit to add specific example

I've copied and pasted your above code, so any errors will remain here, but it is actually much simpler with execute()

function updateInfo ($columnsToRetrieve, $whereClauseValue) {

    $counter = 1;
    $queryString = 'UPDATE table SET ';
    foreach ($columnsToRetrieve as $k => $V) {
        $queryString .= $k . ' = ?';    
    }
    $queryString .= 'WHERE column4 = ?'
    $stmt = $dbc->dbConnection->prepare($queryString);

    $values = array_values( $columnsToRetrieve );
    $values[] = $whereClauseValue();

    $stmt->execute( $values );
}

With the assistance of @RiggsFolly and @Sebastian Brosch, I was able to better understand the scenario. I looked up some past posts as well, and was able to tailor a possible solution:

$columnsToRetrieve = array('name' => 'Frank', 'phone' => '1112223333');
$email = 't@t.com';

$values = array();

$string = 'UPDATE users SET';

foreach ($columnsToRetrieve as $k => $v) {
    $string .= ' ' . $k . ' = :' . $k . ',';
    $values[':' . $k] = $v;
};

$string = substr($string, 0, -1);

$string .= ' WHERE email = :email;';

$values[':email'] = $email;

try {
    $stmt = $dbc->prepare($string);
    $stmt->execute($values);
} catch (PDOException $e) {
    echo $e->getMessage();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM