Как написать хорошую вставку базы данных PHP, используя ассоциативный массив - PullRequest
10 голосов
/ 16 ноября 2009

В PHP я хочу вставить в базу данных, используя данные, содержащиеся в ассоциативном массиве пар поле / значение.

Пример:

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

Полученная вставка SQL должна выглядеть следующим образом:

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

Я предложил следующую однострочную версию PHP:

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

Он разделяет ключи и значения ассоциативного массива и implodes для генерации строки через запятую. Проблема в том, что он не экранирует и не цитирует значения, которые были вставлены в базу данных. Чтобы проиллюстрировать опасность, представьте, что в $_fields содержится следующее:

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

Будет сгенерирован следующий SQL:

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

К счастью, несколько запросов не поддерживаются , тем не менее, кавычки и экранирование необходимы для предотвращения уязвимостей SQL-инъекций.

Как вы пишете свои PHP Mysql Inserts?

Примечание. Запросы, подготовленные для PDO или mysqli, в настоящее время не подходят для меня, поскольку база кода уже широко использует mysql - изменение запланировано, но для преобразования потребуется много ресурсов?

Ответы [ 7 ]

21 голосов
/ 16 ноября 2009

Единственное, что я хотел бы изменить, это использовать sprintf для удобства чтения

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

и убедитесь, что значения экранированы.

3 голосов
/ 16 ноября 2009

Ничего плохого в этом нет. Я делаю то же самое.

Но убедитесь, что вы mysql_escape() и заключили в кавычки значения, введенные в запросе, в противном случае вы смотрите на уязвимость внедрения SQL.

В качестве альтернативы, вы можете использовать параметризованные запросы, и в этом случае вы можете практически передать сам массив вместо построения строки запроса.

1 голос
/ 16 ноября 2009

Рекомендуется использовать ORM (Doctrine 2.0), реализацию ActiveRecord (Doctrine 1.0, RedBean) или реализацию шаблона TableGateway (Zend_Db_Table, Propel). Эти инструменты сделают вашу жизнь намного проще, справятся с тяжелой работой и защитят вас от SQL-инъекций.

Кроме этого, нет ничего плохого в том, что вы делаете, вы можете просто абстрагировать его в класс или функцию, чтобы вы могли повторить функциональность в разных местах.

0 голосов
/ 04 августа 2016

Если вы хотите улучшить свой подход и добавить возможность проверки входных данных и санитарии, вы можете сделать это:

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).')' );
}
0 голосов
/ 06 декабря 2012

Существует проблема с преобразованием значений NULL (в принятом ответе) в пустую строку "". Так что это исправить, NULL становится NULL без кавычек:

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

    return substr($s, 1);
}

Использование:

implode_sql_values(array_values( array('id'=>1, 'nick'=>'bla', 'fbid'=>NULL) ));
// =='"1","bla",NULL'
0 голосов
/ 24 марта 2010

Я использую это, чтобы получить часть ЗНАЧЕНИЙ ВСТАВКИ. Но это может быть абсурдным способом делать вещи. Комментарии / предложения приветствуются.

   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, " ,") . ")";
   }
0 голосов
/ 17 ноября 2009

Используя трюк sprintf , упомянутый Гален в предыдущем ответе , я получил следующий код:

$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);

Создает экранированную и заключенную в кавычки вставку. Он также справляется независимо от того, включен magic_quotes_gpc или нет. Код мог бы быть лучше, если бы я использовал новые PHP v5.3.0 анонимные функции , но мне нужно, чтобы он работал на старых установках PHP.

Этот код немного длиннее исходного (и медленнее), но он более безопасен.

...