11

在 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 插入?

注意:PDO 或 mysqli 准备的查询目前不是我的选择,因为代码库已经广泛使用 mysql - 计划进行更改但需要大量资源来转换?

4

7 回答 7

22

我唯一要改变的就是使用 sprintf 来提高可读性

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

并确保值被转义。

于 2009-11-16T19:12:04.310 回答
3

没有错。我也一样。

但请确保您mysql_escape()并引用您在查询中粘贴的值,否则您正在查看 SQL 注入漏洞。

或者,您可以使用参数化查询,在这种情况下,您实际上可以传递数组本身,而不是构建查询字符串。

于 2009-11-16T19:08:09.203 回答
1

最佳实践是使用 ORM(Doctrine 2.0)、ActiveRecord 实现(Doctrine 1.0、RedBean)或 TableGateway 模式实现(Zend_Db_Table、Propel)。这些工具将使您的生活变得更轻松,并为您处理大量繁重的工作,并有助于保护您免受 SQL 注入。

除此之外,您所做的事情本质上没有任何问题,您可能只是想将其抽象为一个类或一个函数,以便您可以在不同的地方重复该功能。

于 2009-11-16T19:08:26.830 回答
0

使用Galen之前的回答中提到的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 安装上运行。

此代码比原始代码稍长(且速度较慢),但更安全。

于 2009-11-17T17:58:54.520 回答
0

我用它来检索 INSERT 的 VALUES 部分。但这可能是一种荒谬的做事方式。欢迎评论/建议。

   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, " ,") . ")";
   }
于 2010-03-24T18:41:01.287 回答
0

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'
于 2012-12-06T13:43:06.130 回答
0

如果您想增强您的方法并增加输入验证和卫生的可能性,您可能需要这样做:

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).')' );
}
于 2016-08-04T11:30:54.943 回答