2010-01-23 6 views
5

J'ai un problème avec l'objet PDO de PHP pour préparer une instruction de mise à jour et mettre à jour l'enregistrement. J'ai pris la requête SQL brute et l'ai exécutée dans phpMyAdmin avec les params remplacés par leurs valeurs qui sont passées à la fonction. Ce qui met à jour l'enregistrement comme prévu. Cependant, lorsqu'il est exécuté à partir du script, il ne se met pas à jour. Il renvoie zéro erreur et renvoie une réponse errorInfo() de 00000, ce qui, selon moi, est la façon de dire que tout va bien. Je sais que l'objet PDO fonctionne parce qu'il insère et sélectionne avec succès les enregistrements de la base de données, y compris celui que j'essaye de mettre à jour. Je comprends que cette fonction de mise à jour est moche, j'apprends juste le PDO.PHP PDO Instruction de requête préparée ne mettant pas à jour l'enregistrement

Évidemment, ceci est codé en PHP5, en utilisant PDO.

Classe Fonction:

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

appelé à partir du script session de mise à jour/login:

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

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

sortie de echos et print_r en fonction de la classe et l'appelant:

// 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 
) 

Répondre

2

Je ne Je ne sais pas grand-chose à propos de PDO, mais j'ai l'impression qu'il y a quelque chose qui ne va pas dans la façon dont vous liez les paramètres. Cependant, la façon la plus simple de dire à coup sûr est de voir la requête réelle.

Selon le , vous devriez être en mesure de voir la requête générée comme il est allé à SQL dans $stmt->queryString. Il n'est pas possible de voir maintenant car vous liez les paramètres à l'instruction après vous produisez en sortie $stmt.

Effectuez un print_r() après avoir lié les paramètres (ou peut-être même après l'exécution de la requête, je ne sais pas). Vous devriez obtenir la vraie chaîne de requête, et aller au fond du problème.

+0

J'ai inclus la chaîne de requête dans la question d'origine. [queryString] => mise à jour des utilisateurs set 'twitter_key' = 'twitter_key',' twitter_secret' = ': twitter_secret' où id = ': id' LIMIT 1; Cependant, juste pour être 100%, nous obtenons le dernier queryString que je peux voir J'ai suivi vos instructions et les résultats retournent la même chaîne: queryString: mise à jour des utilisateurs set 'twitter_key' = ': twitter_key',' twitter_secret' = ': twitter_secret' où id = ': id' LIMIT 1; qui correspond également au retour de $ stmt-> debugDumpParams() – Jayrox

+0

Non, c'est la requête non traitée, n'est-ce pas? Vous n'envoyez pas la valeur ': twitter_key' à la base de données? Cela n'aurait aucun sens, n'est-ce pas? –

+0

c'est correct, ça fait un peu de magie et change le: twitter_key à la valeur. Je ne sais pas comment faire imprimer la requête avec les valeurs passées ou même si c'est réellement possible. – Jayrox

1

Fonction de classe corrigée qui fonctionne ... Placée ici au cas où quelqu'un aimerait, apprendre, utiliser ou quoi que ce soit.

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