PDO PHP insert into DB from an associative array

前端 未结 6 928
鱼传尺愫
鱼传尺愫 2020-12-06 07:01

I have an array like this

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

When I do a var-dump I get th

相关标签:
6条回答
  • 2020-12-06 07:21

    Last time I checked, it was not possible to prepare a statement where the affected columns were unknown at preparation time - but that thing seems to work - maybe your database system is more forgiving than those I am using (mainly postgres)

    What is clearly wrong is the implode() statement, as each variable should be handled by it self, you also need parenthesis around the field list in the insert statement.

    To insert user defined fields, I think you have to do something like this (at least that how I do it);

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

    If you cannot trust the field names in $a, you have to do something like

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

    Where validfields is a function that you write that tests each fieldname and checks if it is valid (quick and dirty by making an associative array $valfields=array('name'=>1,'email'=>1, 'phone'=>1 ... and then checking for the value of $valfields[$f], or (as I would prefer) by fetching the field names from the server)

    0 讨论(0)
  • 2020-12-06 07:24

    Because all other answers allow SQL injection. For user input you need to filter for allowed field names:

    // 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);
    
    0 讨论(0)
  • 2020-12-06 07:43

    SQL query parameters can be used only where you would otherwise put a literal value.

    So if you could see yourself putting a quoted string literal, date literal, or numeric literal in that position in the query, you can use a parameter.

    You can't use a parameter for a column name, a table name, a lists of values, an SQL keyword, or any other expressions or syntax.

    For those cases, you still have to interpolate content into the SQL string, so you have some risk of SQL injection. The way to protect against that is with whitelisting the column names, and rejecting any input that doesn't match the whitelist.

    0 讨论(0)
  • 2020-12-06 07:44

    You actually can have the :phone and :image fields bound with null values in advance. The structure of the table is fixed anyway and you probably should got that way.


    But the answer to your question might look like this:

    $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));
    
    0 讨论(0)
  • 2020-12-06 07:44

    I know this question has be answered a long time ago, but I found it today and have a little contribution in addition to the answer of @MortenSickel.

    The class below will allow you to insert or update an associative array to your database table. For more information about MySQL PDO please visit: 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 class usage:

    <?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);
    ?>
    
    0 讨论(0)
  • 2020-12-06 07:46

    I appreciated MortenSickel's answer, but I wanted to use named parameters to be on the safe side:

        $keys = array_keys($a);
        $sql = "INSERT INTO user (".implode(", ",$keys).") \n";
        $sql .= "VALUES ( :".implode(", :",$keys).")";        
        $q = $this->dbConnection->prepare($sql);
        return $q->execute($a);
    
    0 讨论(0)
提交回复
热议问题