Comment écrire une bonne insertion dans la base de PHP en utilisant un tableau associatif

StackOverflow https://stackoverflow.com/questions/1744168

  •  20-09-2019
  •  | 
  •  

Question

En PHP, je veux insérer dans une base de données en utilisant les données contenues dans un tableau associatif de paires champ / valeur.

Exemple:

$_fields = array('field1'=>'value1','field2'=>'value2','field3'=>'value3');

L'insert SQL résultant devrait se présenter comme suit:

INSERT INTO table (field1,field2,field3) VALUES ('value1','value2','value3');

Je suis venu avec le PHP suivant une doublure:

mysql_query("INSERT INTO table (".implode(',',array_keys($_fields)).") VALUES (".implode(',',array_values($_fields)).")");

Il sépare les clés et les valeurs du tableau associatif et implodes pour générer une chaîne de caractères séparés par des virgules. Le problème est qu'il n'échappe pas ou citer les valeurs qui ont été insérées dans la base de données. Pour illustrer le danger, Imaginez si $_fields contenait les éléments suivants:

$_fields = array('field1'=>"naustyvalue); drop table members; --");

Le SQL suivante sera générée:

INSERT INTO table (field1) VALUES (naustyvalue); drop table members; --;

Par chance, plusieurs requêtes ne sont pas pris en charge , citant néanmoins et échapper sont essentiels pour prévenir les vulnérabilités d'injection SQL.

Comment écrivez-vous votre PHP Mysql Inserts?

Remarque: AOP ou mysqli requêtes préparées ne sont pas actuellement une option pour moi parce que le code de base utilise déjà largement MySQL - un changement est prévu, mais il prendrait beaucoup de ressources pour convertir

Était-ce utile?

La solution

La seule chose que je changerais serait d'utiliser sprintf pour des raisons de lisibilité

$sql = sprintf(
    'INSERT INTO table (%s) VALUES ("%s")',
    implode(',',array_keys($_fields)),
    implode('","',array_values($_fields))
);
mysql_query($sql);

et assurez-vous que les valeurs sont échappés.

Autres conseils

Rien de mal à cela. Je fais la même chose.

Mais assurez-vous mysql_escape() et indiquez les valeurs que vous coller dans la requête, sinon vous cherchez à la vulnérabilité d'injection SQL.

Alternativement, vous pouvez utiliser des requêtes paramétrées, dans ce cas, vous pouvez pratiquement passer le tableau en lui-même, au lieu de construire une chaîne de requête.

La meilleure solution consiste soit à utiliser un ORM (Doctrine 2.0), une mise en œuvre ActiveRecord (doctrine 1,0, redbean), ou une mise en œuvre du motif de TableGateway (Zend_Db_Table, Propel). Ces outils feront de votre vie beaucoup plus facile, et gérer beaucoup de soulever des charges lourdes pour vous et peut vous aider à protéger des injections SQL.

En dehors de cela, il n'y a rien d'intrinsèquement mauvais avec ce que vous faites, vous pourriez vouloir abstraire loin dans une classe ou d'une fonction, de sorte que vous pouvez répéter la fonctionnalité dans des endroits différents.

Utilisation sprintf trick mentionné par Galen dans un réponse précédente , je suis venu avec le code suivant:

$escapedfieldValues = array_map(create_function('$e', 'return mysql_real_escape_string(((get_magic_quotes_gpc()) ? stripslashes($e) : $e));'), array_values($_fields));

$sql = sprintf('INSERT INTO table (%s) VALUES ("%s")', implode(',',array_keys($_fields)), implode('","    ',$escapedfieldValues));

mysql_query($sql);

Il génère un insert échappé et cité. Il se débrouille également indépendamment du fait que magic_quotes_gpc est activée ou désactivée. Le code pourrait être mieux si je nouvelle v5.3.0 PHP fonctions anonymes mais j'ai besoin pour fonctionner sur les installations PHP plus.

Ce code est un peu plus que l'original (et plus lent), mais il est plus sûr.

J'utilise ceci pour récupérer les valeurs de la partie INSERT. Mais ce pourrait être un moyen absurde de faire des choses. Commentaires / suggestions sont les bienvenus.

   function arrayToSqlValues($array)
   {
      $sql = "";
      foreach($array as $val)
      {    
         //adding value
         if($val === NULL)
            $sql .= "NULL";
         else
            /*
            useless piece of code see comments
            if($val === FALSE)
               $sql .= "FALSE";
            else
            */
               $sql .= "'" . addslashes($val) . "'";

         $sql .= ", ";
      };

      return "VALUES(" . rtrim($sql, " ,") . ")";
   }

Il y a un problème avec NULL (dans la réponse acceptée) Les valeurs étant converties en une chaîne vide « ». Donc, c'est fixe, NULL devient NULL sans les guillemets:

function implode_sql_values($vals)
{
    $s = '';
    foreach ($vals as $v)
        $s .= ','.(($v===NULL)?'NULL':'"'.mysql_real_escape_string($v).'"');

    return substr($s, 1);
}

Utilisation:

implode_sql_values(array_values( array('id'=>1, 'nick'=>'bla', 'fbid'=>NULL) ));
// =='"1","bla",NULL'

Si vous voulez améliorer votre approche et ajouter la possibilité de validation d'entrée et de l'assainissement, vous pouvez faire ceci:

function insertarray($table, $arr){
   foreach($arr as $k => $v){
      $col[] = sanitize($k);
      $val[] = "'".sanitize($v)."'";
   }

   query('INSERT INTO '.sanitize($table).' ('.implode(', ', $col).') VALUES ('.implode(', ', $val).')' );
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top