PHP PDO Prepared statement query not updating reco

2020-02-06 03:30发布

问题:

I am having a problem using PHP's PDO object to prepare an update statement and updating the record. I have taken the raw SQL query and ran it in phpMyAdmin with the params replaced by their values that are passed to the function. Which updates the record as intended. However, when ran from the script it does not update. It throws zero errors and it returns an errorInfo() reply of 00000, which to my understanding is PDO's way of saying all is well. I know the PDO object works because it successfully inserts and selects records from the database, including the one I am trying to update. I understand this update function is ugly, I am just learning PDO.

Obviously, this is coded in PHP5, using PDO.

Class Function:

public function update($tbl_name, $where = null, $what = null)
    {
        if(is_array($where))
        {
            $where_str = 'where ';
            foreach($where as $key => $val)
            {
                $where_str .= "{$key} = ':{$key}' and ";
            }
            $where_str = substr($where_str,0,-5);

            $what_str = 'set ';
            foreach($what as $key => $val)
            {
                $what_str .= "`{$key}` = ':{$key}', ";
            }
            $what_str = substr($what_str,0,-2);

            $query_str = "update {$tbl_name} {$what_str} {$where_str} LIMIT 1;";
            $stmt = $this->dbh->prepare($query_str);
            echo '<pre>'.print_r($stmt, true).'</pre>';
            foreach($what as $key => $val)
            {
                if('date_time' === $key) continue;
                $bind = $stmt->bindValue(":{$key}",$val);
                echo ($bind ? 'true' : 'false')." :{$key}=",$val,'<br/>';
            }
            foreach($where as $key => $val)
            {
                if('date_time' === $key) continue;
                $bind = $stmt->bindValue(":{$key}",$val);
                echo ($bind ? 'true' : 'false')." :{$key} ",$val,'<br/>';
            }
        }else{
            return false;
        }
        $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $exec = $stmt->execute();
        echo 'exec: '.($exec === true ? 'true:' : 'false:').':'.$exec.'<br/>';

        echo '<pre>';
        $stmt->debugDumpParams();
        echo '</pre>';

        return $stmt->errorInfo();
    }

Called from session update/login script:

$where = array(
    'id' => $user['id'],
    );
$what = array(
    'twitter_key'    => $oauth_token,
    'twitter_secret' => $oauth_token_secret
    );

$update = $db->update('users', $where, $what);

Output from echos and print_r in class function and caller:

// print_r($stmt = $this->dbh->prepare($query_str)) output:
PDOStatement Object
(
    [queryString] => update users set `twitter_key` = ':twitter_key', `twitter_secret`     = ':twitter_secret' where id = ':id' LIMIT 1;
)

// output from the bing params and execution returns
true :twitter_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXX
true :twitter_secret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
true :id 20
exec: true:1

// $stmt->debugDumpParams() output: 
SQL: [111] update users set `twitter_key` = ':twitter_key', `twitter_secret` = ':twitter_secret' where id = ':id' LIMIT 1;
Params:  3
Key: Name: [12] :twitter_key
paramno=-1
name=[12] ":twitter_key"
is_param=1
param_type=2
Key: Name: [15] :twitter_secret
paramno=-1
name=[15] ":twitter_secret"
is_param=1
param_type=2
Key: Name: [3] :id
paramno=-1
name=[3] ":id"
is_param=1
param_type=2

// print_r($stmt->errorInfo()) output:
Array
(
    [0] => 00000
)

回答1:

I don't know much about PDO, but my feeling is there is something wrong with the way you bind the parameters. However, the easiest way to tell for sure is to see the actual query.

According to the docs, you should be able to see the generated query as it went to SQL in $stmt->queryString. It's not possible to see right now because you are binding the parameters to the statement after you are outputting $stmt.

Do a print_r() after you bind the parameters (or maybe even after execution of the query, I don't know). You should get the real query string, and get to the bottom of the problem.



回答2:

Corrected class function that works... Placed here in case someone would like it, to learn from, to use or what ever.

public function update($tbl_name, $where = null, $what = null)
    {
        if(is_array($where) && is_array($what))
        {
            $where_str = 'where ';
            foreach($where as $key => $val)
            {
                $where_str .= "{$key} = :{$key} and ";
            }
            $where_str = substr($where_str,0,-5);

            $what_str = 'set ';
            foreach($what as $key => $val)
            {
                $what_str .= "{$key} = :{$key}, ";
            }
            $what_str = substr($what_str,0,-2);

            $query_str = "update {$tbl_name} {$what_str} {$where_str} LIMIT 1;";
            $stmt = $this->dbh->prepare($query_str);
            foreach($what as $key => $val)
            {
                if('date_time' === $key) continue;
                $bind = $stmt->bindValue(":{$key}",$val);
            }
            foreach($where as $key => $val)
            {
                if('date_time' === $key) continue;
                if('id' === $key)
                {
                    $bind = $stmt->bindValue(":{$key}",$val, PDO::PARAM_INT);
                }else{
                    $bind = $stmt->bindValue(":{$key}",$val);
                }
            }
        }else{
            return false;
        }
        $stmt->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $exec = $stmt->execute();
        return $stmt->errorInfo();
    }