2

I'm editing a script that is using MySQLi. I need to use prepared statement to insert some values into the db.

My array is in the form of:

$insert = array('column1' => 'value1', 'column2' => 'value2', 'column3' => 'value3')

I have this so far but I need help with the bind_param portion. I've seen documentation on here where call_user_func_array is used but I'm not sure how to implement this.

$cols = array_keys($insert);
$query = "INSERT IGNORE INTO results (". implode(", ", $cols) .") VALUES (". implode(', ', array_fill(0, count($insert), '?')) .")";
$stmt = $mysqli->prepare($query);
$param = array_merge(array(str_repeat('s', count($insert))), array_values($insert)); 
call_user_func_array(array($stmt, 'bind_param'), $param); 
$stmt->execute();

PHP 5.4.17

Allan Thomas
  • 3,481
  • 5
  • 26
  • 29
  • 2
    The PHP.net docs do a good job of explaining the function: http://php.net/manual/en/mysqli-stmt.bind-param.php – SamA Oct 29 '13 at 18:11
  • Thanks but that was my first destination. I haven't been able to completely figure it out. – Allan Thomas Oct 29 '13 at 18:14
  • @allanb, look into the comment with example of ReflectionClass (upper comment) in the link of SamA. –  Oct 29 '13 at 18:17
  • 1
    Duplicate of http://stackoverflow.com/questions/3681262/php5-3-mysqli-stmtbind-params-with-call-user-func-array-warnings ? – AbraCadaver Oct 29 '13 at 18:22
  • take a look at this: http://no2.php.net/manual/en/mysqli-stmt.bind-param.php#89171 – Mojtaba Oct 29 '13 at 18:31
  • what version of PHP are you on? – gloomy.penguin Oct 29 '13 at 18:47
  • I'm not sure if prepared statements are a good option in PHP for most cases. Prepared statements can be of good performance optimization when you are going to use the same query multiple times in the same run, but doing that is never too practical in web development. So except for the code styling factor, its of little value to use prepared statements in PHP. – Havenard Oct 29 '13 at 20:50

2 Answers2

6

No... this was definitely harder than PDO with any array because of how mysqli_stmt_bind_param() works... and this works fine by changing $array to removing/adding data for other columns.

$mysqli = new mysqli('localhost', 'root', 'password', 'test');

$array  = array("name"=>"pineapple", "color"=>"purple"); 

$table_name = "fruit"; 



insert_data($mysqli, $array, $table_name);



function insert_data($mysqli, $array, $table_name) 
{
   $placeholders = array_fill(0, count($array), '?');

   $keys   = array(); 
   $values = array();
   foreach($array as $k => $v) {
      $keys[] = $k;
      $values[] = !empty($v) ? $v : null;
   }

   $query = "insert into $table_name ".
            '('.implode(', ', $keys).') values '.
            '('.implode(', ', $placeholders).'); '; 
   // insert into fruit (name, color) values (?, ?);    

   $stmt = $mysqli->prepare($query);

   // create a by reference array... 
   $params = array(); 
   foreach ($array as &$value) { 
      $params[] = &$value;
   }
   $types  = array(str_repeat('s', count($params))); 
   $values = array_merge($types, $params); 

   /*           
   $values = Array
      (
          [0] => ss
          [1] => pineapple
          [2] => purple
      ) 
   */

   call_user_func_array(array($stmt, 'bind_param'), $values); 

   $success = $stmt->execute();

   if ($success) { print "it worked..."; } 
           else { print "it did not work..."; }
}  

I got some help from these SO posts:
- https://stackoverflow.com/a/15933696/623952
- https://stackoverflow.com/a/6179049/623952


So... in $stmt->bind_param() the first parameter is a string that has one char for each parameter passed in. And that char represents the parameter data type. In the example above, both of the two parameters are strings so it becomes ss. A string is always assumed in the example above, too.

I found this chart in the bind_param() documentation:

types
A string that contains one or more characters which specify the types for the corresponding bind variables:

Type specification chars  

Character    Description  
i            corresponding variable has type integer
d            corresponding variable has type double
s            corresponding variable has type string
b            corresponding variable is a blob and will be sent in packets
Community
  • 1
  • 1
gloomy.penguin
  • 5,833
  • 6
  • 33
  • 59
  • This is PDO, whereas the question was about mysqli. – eggyal Oct 29 '13 at 18:27
  • oh! well that's almost easier for me... i just did a lot of work for nothing. lol... hold on – gloomy.penguin Oct 29 '13 at 18:27
  • Thx. But `Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object` which is what I got when I attempted this. – Allan Thomas Oct 29 '13 at 19:56
  • it works for me...? I can copy and paste it again but for me, it runs fine and updates my database. have you been able to figure out what php version you are running yet? maybe you should update your question with the new code that shows the error... you might have made an error merging the code? – gloomy.penguin Oct 29 '13 at 20:00
  • How do you do when the $types is a mixture of strings and integer – 4Jean Nov 12 '17 at 13:03
  • How do you do when the $types is a mixture of strings and integer – 4Jean Nov 12 '17 at 13:03
0

I think this is what you are looking for:

cols = array_keys($insert);
$query = "INSERT INTO results (". implode(", ", $cols) .") VALUES (". str_repeat('?', count($insert)) .")";
$stmt = $mysqli->prepare($query);

call_user_func_array('mysqli_stmt_bind_param', array_merge (array($stmt, str_repeat('s', count($insert))), $insert); 
SamA
  • 587
  • 3
  • 6