9

我有一个这样的数组

  $a = array( 'phone' => 111111111, 'image' => "sadasdasd43eadasdad" );

当我执行 var-dump 时,我得到了这个 ->

 { ["phone"]=> int(111111111) ["image"]=> string(19) "sadasdasd43eadasdad" }

现在我正在尝试使用 IN 语句将其添加到数据库中-

 $q = $DBH->prepare("INSERT INTO user :column_string VALUES :value_string");
 $q->bindParam(':column_string',implode(',',array_keys($a)));
 $q->bindParam(':value_string',implode(',',array_values($a)));
 $q->execute();

我遇到的问题是内爆返回一个字符串。但是“电话”列是数据库中的整数,并且数组也将其存储为整数。因此,我收到 SQL 错误,因为我的最终查询如下所示——

INSERT INTO user 'phone,image' values '111111111,sadasdasd43eadasdad';

这是一个错误的查询。有没有办法解决它。

我的列名是动态的,基于用户想要插入的内容。所以我不能使用:phone:image之类的占位符,因为我可能并不总是获得这两列的值。如果有办法解决这个问题,请告诉我。否则我将不得不为每种类型的更新定义多个函数。

谢谢。

4

7 回答 7

10

上次我检查时,不可能准备一个在准备时受影响的列未知的语句-但这似乎可行-也许您的数据库系统比我使用的数据库系统更宽容(主要是 postgres)

显然错误的是 implode() 语句,因为每个变量都应该由它自己处理,因此您还需要在插入语句中的字段列表周围加上括号。

要插入用户定义的字段,我认为你必须做这样的事情(至少我是这样做的);

$fields=array_keys($a); // here you have to trust your field names! 
$values=array_values($a);
$fieldlist=implode(',',$fields); 
$qs=str_repeat("?,",count($fields)-1);
$sql="insert into user($fieldlist) values(${qs}?)";
$q=$DBH->prepare($sql);
$q->execute($values);

如果您不能信任 $a 中的字段名称,则必须执行类似的操作

foreach($a as $f=>$v){
   if(validfield($f)){
      $fields[]=$f;
      $values[]=$v;
   }
}

其中 validfields 是您编写的一个函数,它测试每个字段名并检查它是否有效(通过创建关联数组 $valf​​ields=array('name'=>1,'email'=>1, 'phone'= >1 ... 然后检查 $valf​​ields[$f] 的值,或者(如我所愿)通过从服务器获取字段名称)

于 2012-11-22T07:51:55.920 回答
6

SQL 查询参数只能用于您本来要放置文字值的地方。

因此,如果您可以看到自己在查询中的该位置放置了带引号的字符串文字、日期文字或数字文字,则可以使用参数。

您不能将参数用于列名、表名、值列表、SQL 关键字或任何其他表达式或语法。

对于这些情况,您仍然需要将内容插入到 SQL 字符串中,因此您有一些 SQL 注入的风险。防止这种情况的方法是将列名列入白名单,并拒绝任何与白名单不匹配的输入。

于 2012-11-22T08:06:06.360 回答
4

因为所有其他答案都允许SQL 注入。对于用户输入,您需要过滤允许的字段名称:

// change this
$fields = array('email', 'name', 'whatever');
$fieldlist = implode(',', $fields);
$values = array_values(array_intersect_key($_POST, array_flip($fields)));
$qs = str_repeat("?,",count($fields)-1) . '?';
$q = $db->prepare("INSERT INTO events ($fieldlist) values($qs)");
$q->execute($values);
于 2016-06-02T12:11:00.543 回答
3

我很欣赏 MortenSickel 的回答,但为了安全起见,我想使用命名参数:

    $keys = array_keys($a);
    $sql = "INSERT INTO user (".implode(", ",$keys).") \n";
    $sql .= "VALUES ( :".implode(", :",$keys).")";        
    $q = $this->dbConnection->prepare($sql);
    return $q->execute($a);
于 2015-05-21T22:58:31.530 回答
2

我知道这个问题很久以前就已经回答了,但是我今天找到了它,除了@MortenSickel的回答之外还有一点贡献。

下面的类将允许您将关联数组插入或更新到数据库表中。有关 MySQL PDO 的更多信息,请访问: http: //php.net/manual/en/book.pdo.php

<?php

class dbConnection
{
  protected $dbConnection;

  function __construct($dbSettings) {
    $this->openDatabase($dbSettings);
  }

  function openDatabase($dbSettings) {  
    $dsn = 'mysql:host='.$dbSettings['host'].';dbname='.$dbSettings['name'];
    $this->dbConnection = new PDO($dsn, $dbSettings['username'], $dbSettings['password']);
    $this->dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  }

  function insertArray($table, $array) {
    $fields=array_keys($array);
    $values=array_values($array);
    $fieldlist=implode(',', $fields); 
    $qs=str_repeat("?,",count($fields)-1);

    $sql="INSERT INTO `".$table."` (".$fieldlist.") VALUES (${qs}?)";

    $q = $this->dbConnection->prepare($sql);
    return $q->execute($values);
  }

  function updateArray($table, $id, $array) {
    $fields=array_keys($array);
    $values=array_values($array);
    $fieldlist=implode(',', $fields); 
    $qs=str_repeat("?,",count($fields)-1);
    $firstfield = true;

    $sql = "UPDATE `".$table."` SET";
    for ($i = 0; $i < count($fields); $i++) {
        if(!$firstfield) {
        $sql .= ", ";   
        }
        $sql .= " ".$fields[$i]."=?";
        $firstfield = false;
    }
    $sql .= " WHERE `id` =?";

    $sth = $this->dbConnection->prepare($sql);
    $values[] = $id;
    return $sth->execute($values);
  }
}
?>

dbConnection 类用法:

<?php
  $dbSettings['host'] = 'localhost';
  $dbSettings['name'] = 'databasename';
  $dbSettings['username'] = 'username';
  $dbSettings['password'] = 'password';
  $dbh = new dbConnection( $dbSettings );

  $a = array( 'phone' => 111111111, 'image' => "sadasdasd43eadasdad" );
  $dbh->insertArray('user', $a);

  // This will asume your table has a 'id' column, id: 1 will be updated in the example below:
  $dbh->updateArray('user', 1, $a);
?>
于 2015-01-07T18:26:20.897 回答
2

您实际上可以提前将:phoneand字段与空值绑定。:image无论如何,表格的结构是固定的,您可能应该这样做。


但是您的问题的答案可能如下所示:

$keys = ':' . implode(', :', array_keys($array)); 
$values = str_repeat('?, ', count($array)-1) . '?';

$i = 1;
$q = $DBH->prepare("INSERT INTO user ($keys) VALUES ($values)");

foreach($array as $value)
    $q->bindParam($i++, $value, PDO::PARAM_STR, mb_strlen($value));
于 2012-11-22T08:45:44.200 回答
0
public function insert($data = [] , $table = ''){
    $keys = array_keys($data);
    $fields = implode(',',$keys);
    $pre_fields = ':'.implode(', :',$keys);
    $query = parent::prepare("INSERT INTO $table($fields) VALUES($pre_fields) ");
    return $query->execute($data);
}
于 2021-07-15T19:48:47.123 回答