2

J'ai un problème avec ma classe de base de données. J'ai une méthode qui prend une instruction préparée et un nombre quelconque de paramètres, les lie à l'instruction, exécute l'instruction et met en forme le résultat dans un tableau multidimensionnel. Everthing fonctionne bien jusqu'à ce que j'essaie d'inclure une adresse e-mail dans l'un des paramètres. L'email contient un caractère @ et celui-ci semble tout casser. Quand je l'offre avec des paramètres:Impossible de lier la chaîne contenant @ char avec mysqli_stmt_bind_param

$types = "ss" and $parameters = array("[email protected]", "testtest") 

Je reçois l'erreur:

Warning: Parameter 3 to mysqli_stmt_bind_param() expected to be a reference, value given in ...db/Database.class.php on line 63

Voici la méthode:

private function bindAndExecutePreparedStatement(&$statement, $parameters, $types) { 
    if(!empty($parameters)) { 
     call_user_func_array('mysqli_stmt_bind_param', array_merge(array($statement, $types), &$parameters)); 
     /*foreach($parameters as $key => $value) { 
      mysqli_stmt_bind_param($statement, 's', $value); 
     }*/ 
    } 

    $result = array(); 

    $statement->execute() or debugLog("Database error: ".$statement->error); 

    $rows = array(); 

    if($this->stmt_bind_assoc($statement, $row)) { 
     while($statement->fetch()) { 
      $copied_row = array(); 
      foreach($row as $key => $value) { 
       if($value !== null && mb_substr($value, 0, 1, "UTF-8") == NESTED) { // If value has a nested result inside 
        $value = mb_substr($value, 1, mb_strlen($value, "UTF-8") - 1, "UTF-8"); 
        $value = $this->parse_nested_result_value($value); 
       } 
       $copied_row[$ke<y] = $value; 
      } 
      $rows[] = $copied_row; 
     } 
    } 

    // Generate result 
    $result['rows'] = $rows; 
    $result['insert_id'] = $statement->insert_id; 
    $result['affected_rows'] = $statement->affected_rows; 
    $result['error'] = $statement->error; 

    return $result; 
} 

J'ai eu une suggestion que:

the array_merge is casting parameter to string in the merge change it to &$parameters so it remains a reference

Alors j'ai essayé à (3ème ligne de la méthode), mais cela n'a pas fait de différence.

Comment faire? Y at-il une meilleure façon de le faire sans call_user_func_array?


mise à jour: J'ai trouvé une façon moins jolie de résoudre cela. Ce que j'ai fait était de créer un nouveau tableau de référence avec une boucle et d'utiliser celui-ci à la place.

private function bindAndExecutePreparedStatement($statement, $parameters, $types) 
{ 
    if(!empty($parameters)) { 
     $parameters_references = array(); 
     foreach($parameters as $key => $parameter) { 
      $parameters_references[] = &$parameters[$key]; 
     } 
     call_user_func_array('mysqli_stmt_bind_param', 
      array_merge(array($statement, $types), $parameters_references)); 
    } 
    .... 

Je suis toujours intéressé à résoudre ce avec AOP, il semble l comme il a beaucoup d'autres fonctionnalités aussi bien. Je n'ai juste pas encore appris à l'utiliser.

Répondre

1

J'ai écrit le code de liaison de paramètres dans l'adaptateur MySQLi de Zend Framework. Je trouve l'API de liaison de paramètres pour MySQLi difficile à utiliser. Ce n'est pas le tableau qui doit être une référence, c'est chaque élément du tableau.

Vous pouvez voir le code que j'ai écrit dans la méthode _execute() dans cette classe: http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Db/Statement/Mysqli.php

Je vous recommande de vérifier AOP. C'est beaucoup plus facile à utiliser. Vous pouvez lier des paramètres, mais il est encore plus facile de simplement passer le tableau de valeurs de paramètres sous la forme d'un tableau à la méthode execute() de PDOStatement.

+0

Merci, je vais faire un peu de lecture. :-) – Tirithen

+0

J'ai trouvé une façon moins jolie de résoudre ceci: fonction privée bindAndExecutePreparedStatement ($ statement, les paramètres $, $ types) {\ n si { $ parameters_references = array ((vide (paramètres $)!)) foreach (paramètres $ comme paramètre $ key => $) { $ parameters_references [] = & $ parameters [$ key]; } call_user_func_array ('mysqli_stmt_bind_param', array_merge (tableau ($ statement, $ types), $ parameters_references)); } Je suis toujours intéressé à résoudre ce problème avec PDO, il semble que j'ai beaucoup d'autres fonctionnalités. Je n'ai juste pas encore appris à l'utiliser. – Tirithen

+0

Le commentaire ci-dessus a été un peu brouillon mais ce que j'ai fait était de créer un nouveau tableau de référence avec une boucle et d'utiliser celui-ci à la place. – Tirithen