2011-02-24 3 views
10

Il ya quelque chose que je ne comprends pas du tout qui est prepare et query dans mysqli.MySQLi: requête VS préparer

Celui-ci utilise mysqli::query pour traiter la requête et il a été connu de la sécurité manque:

public function fetch_assoc($query) 
    { 
     $result = parent::query($query); 
     //$result = self::preparedStatement($query); 
     if($result) 
     { 
      return $result->fetch_assoc(); 
     } 
     else 
     { 
      # call the get_error function 
      return self::get_error(); 
      # or: 
      # return $this->get_error(); 
     } 
    } 

c'est celui qui prépare-bind-exécution qui a une meilleure sécurité, je suppose,

public function fetch_assoc_stmt($sql,$types = null,$params = null) 
    { 
     # create a prepared statement 
     $stmt = parent::prepare($sql); 

     # bind parameters for markers 
     # but this is not dynamic enough... 
     //$stmt->bind_param("s", $parameter); 

     if($types&&$params) 
     { 
      $bind_names[] = $types; 
      for ($i=0; $i<count($params);$i++) 
      { 
       $bind_name = 'bind' . $i; 
       $$bind_name = $params[$i]; 
       $bind_names[] = &$$bind_name; 
      } 
      $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); 
     } 

     # execute query 
     $stmt->execute(); 

     # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc() 
     $meta = $stmt->result_metadata(); 

     while ($field = $meta->fetch_field()) { 
      $var = $field->name; 
      $$var = null; 
      $parameters[$field->name] = &$$var; 
     } 

     call_user_func_array(array($stmt, 'bind_result'), $parameters); 

     while($stmt->fetch()) 
     { 
      return $parameters; 
     } 

     # close statement 
     $stmt->close(); 
    } 

Cependant, ces deux méthodes deux le même résultat,

$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME); 

$sql = " 
SELECT * 
FROM root_contacts_cfm 
ORDER BY cnt_id DESC 
"; 
print_r($mysqli->fetch_assoc_stmt($sql)); 

print_r($mysqli->fetch_assoc($sql)); 

ils imprimer ceci:

Array 
(
    [cnt_id] => 2 
    [cnt_email1] => [email protected] 
    [cnt_email2] => 
    [cnt_fullname] => Lau T 
    [cnt_firstname] => Thiam 
    [cnt_lastname] => Lau 
    [cnt_organisation] => 
    [cnt_website] => 
    [cnt_biography] => 
    [cnt_gender] => 
    [cnt_birthday] => 
    [cnt_address] => 
    [cnt_postcode] => 
    [cnt_telephone] => 
    [cnt_note] => 
    [cnt_key] => 
    [cat_id] => 
    [tcc_id] => 
    [cnt_suspended] => 0 
    [cnt_created] => 2011-02-04 00:00:00 
    [cnt_updated] => 2011-02-04 13:54:36 
) 
Array 
(
    [cnt_id] => 2 
    [cnt_email1] => [email protected] 
    [cnt_email2] => 
    [cnt_fullname] => Lau T 
    [cnt_firstname] => Thiam 
    [cnt_lastname] => Lau 
    [cnt_organisation] => 
    [cnt_website] => 
    [cnt_biography] => 
    [cnt_gender] => 
    [cnt_birthday] => 
    [cnt_address] => 
    [cnt_postcode] => 
    [cnt_telephone] => 
    [cnt_note] => 
    [cnt_key] => 
    [cat_id] => 
    [tcc_id] => 
    [cnt_suspended] => 0 
    [cnt_created] => 2011-02-04 00:00:00 
    [cnt_updated] => 2011-02-04 13:54:36 
) 

Vous devriez avoir remarqué que dans la méthode de fetch_assoc_stmt Je ne me fetch_assoc du tout. Probablement aucune chance de l'utiliser car prepare utilise une manière différente de retourner le résultat.

Donc, ma question est depuis que l'utilisation prepare est meilleure que query, pourquoi devrait-il exister fetch_assoc? Ne devrions-nous pas l'oublier ou ne devrions-nous pas l'avoir déprécié? C'est pareil pour fetch_all - pourquoi devrions-nous l'avoir en premier lieu?

Merci.

Répondre

21

Les instructions préparées sont préférables aux requêtes SQL simples lorsque vous utilisez des paramètres pour générer dynamiquement la requête. Dans votre exemple, votre SQL ne contient pas de variables, donc l'utilisation d'une requête simple ou d'une instruction préparée est fonctionnellement équivalente.

Lorsque vous devez modifier les valeurs des paramètres, dans la clause WHERE, par exemple, puis préparé des déclarations vous donnera plus de sécurité:

... 
WHERE col1 = ? AND col2 = ? 

Mais lorsque votre requête est simple et fixe, il peut exiger moins code pour utiliser $mysqli->query($sql) avec fetch_assoc(). Utiliser des requêtes directes plutôt que des déclarations préparées n'est pas une pratique universellement mauvaise, comme certains pourraient vous le faire croire. Lorsque votre requête nécessite un paramétrage ou lorsque la même requête doit être compilée et exécutée à plusieurs reprises, vous bénéficierez de l'instruction préparée.

+0

Jolie bonne explication. –

+0

merci. il est logique ... – laukok

+0

Il convient de noter que, bien que les instructions préparées gèrent des requêtes répétées, elles offrent également une protection d'injection bien supérieure, donc je les utilise même lorsque je n'ai pas besoin de répéter une requête. – meteorainer

0

Désolé, ce n'est pas une réponse, mais je ne suis pas assez bon pour laisser un commentaire.

Il semble qu'il y ait un bug dans votre deuxième fonction. Votre code ne fonctionnera pas correctement pour les requêtes qui renvoient plus d'une ligne. Ne devrait pas cette déclaration de retour soit:

while($stmt->fetch()) { 

    //to dereference 
    $row_copy = $parameters; 
    $return_array[] = $row_copy; 

} 

Et puis la fonction doit se terminer par:

return $return_array; 
Questions connexes