在 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 - 计划进行更改,但需要大量资源来转换?

有帮助吗?

解决方案

我想改变的唯一事情是使用出于可读性目的的sprintf

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

和确保值被转义。

其他提示

没有错。我也一样。

但要确保你mysql_escape()并注明您在查询坚守的价值观,否则,你正在寻找SQL注入漏洞。

可替换地,可以使用参数化的查询,在这种情况下,可以通过实际上本身阵列,而不是建立一个查询字符串。

最好的做法是要么使用ORM(学说2.0),一个ActiveRecord实现(学说1.0,红豆),或一个TableGateway模式实现(Zend_Db_Table类,行走)。这些工具将让您的生活轻松了许多,并处理大量繁重的你,并能帮助您防止SQL注入攻击。

除此之外,没有什么内在的错误,你在做什么,你就可能要抽象它带到一个类或函数,这样就可以在不同的地方重复的功能。

使用 冲刺函数 提到的技巧 盖伦 在一个 之前的回答, ,我想出了以下代码:

$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 安装上运行。

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

我用这个检索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, " ,") . ")";
   }

有与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'

如果你想提高你的方法,并添加了输入验证和卫生设施的可能性,你可能要做到这一点:

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).')' );
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top