mysqli bind_param for array of strings

徘徊边缘 提交于 2019-11-26 15:32:38

You can not bind two variables with one question mark !

For every variable you bind you need one question mark

"bind_param" checks each variable whether it matches the requirements. afterwards the string value is placed between quotes.

This will not work.

"SELECT name FROM table WHERE city IN (?)"; ( becomes too )
$q_prepared->bind_param("s", $cities);
"SELECT name FROM table WHERE city IN ('city1,city2,city3,city4')";

must be.

"SELECT name FROM table WHERE city IN (?,?,?,?)"; ( becomes too )
$q_prepared->bind_param("ssss", $city1,$city2,$city3,$city4);
"SELECT name FROM table WHERE city IN ('city1','city2','city3','city4')";

$query_prepared->bind_param quotes string params one by one.
And the number of variables and length of string types must match the parameters in the statement.

$query_str= "SELECT name FROM table WHERE city IN ('Nashville','Knoxville')";

will become

$query_str= "SELECT name FROM table WHERE city IN (?,?)";

now bind_param must be

bind_param("ss",$arg1,$arg2)

with this

$query_str= "SELECT name FROM table WHERE city IN (?)";

and bind_param with

bind_param("s",$cities)

you get

$query_str= "SELECT name FROM table WHERE city IN ('Nashville,Knoxville')";

That's why an array not works .
The only solution for this fact is call_user_func_array

if you init a statement, following is unnecessary

$query_prepared = $mysqli->stmt_init();
if($query_prepared && $query_prepared->prepare($query_str)) {

This is correct

$query_prepared = $mysqli->stmt_init();
if($query_prepared->prepare($query_str)) {

if you don't want to use call_user_func_array
and you have only a small count of arguments
you can do it with the following code.

[...]
$cities= explode(",", $_GET['cities']);
if (count($cities)>3) { echo "too many arguments"; }
else
{ 
$count = count($cities); 
$SetIn = "(";
  for($i = 0; $i < $count; ++$i) {    
      $code.='s';
      if ($i>0) {$SetIn.=",?";} else {$SetIn.="?";}
  }
$SetIn.=")";
$query_str= "SELECT name FROM table WHERE city IN ".$SetIn;
// with 2 arguments $query_str will look like
// SELECT name FROM table WHERE city IN (?,?)
$query_prepared = $mysqli->stmt_init();
if($query_prepared->prepare($query_str))
  {       
    if ($count==1) { $query_prepared->bind_param($code, $cities[0]);}
    if ($count==2) { $query_prepared->bind_param($code, $cities[0],$cities[1]);}
    if ($count==3) { $query_prepared->bind_param($code, $cities[0],$cities[1],$cities[2]);
    // with 2 arguments $query_prepared->bind_param() will look like
    // $query_prepared->bind_param("ss",$cities[0],$cities[1])      
  }    

    $query_prepared->execute();
  } 
 [...]
 }

I would suggest you try it with call_user_func_array to reach.

look for the solution of nick9v
mysqli-stmt.bind-param

use call_user_func_array like this:

$stmt = $mysqli->prepare("INSERT INTO t_file_result VALUES(?,?,?,?)");

$id = '1111';
$type = 2;
$result = 1;
$path = '/root';

$param = array('siis', &$id, &$type, &$result, &$path);
call_user_func_array(array($stmt, 'bind_param'), $param);

$stmt->execute();

printf("%d row inserted. \n", $stmt->effected_rows);
$stmt->close;

The way I did it: prepare the query with all its separate question marks, as well as the type string.

$cities = array('Nashville','Knoxville');
$dibs = '';
$query = "SELECT name FROM table WHERE city IN (";
$marks = array();

foreach ($cities as $k => $city) {
    // i,s,b,d type based on the variables to bind.
    $dibs .= 's';
    array_push($marks, '?');
}

$query .= implode(',', $marks) .')';

Connect.

$mysql = new mysqli($host, $user, $pass, $dbname);
$statement =
    $mysql->prepare($query)
OR  die(sprintf(
        'Query error (%s) %s', $mysql->errno, $mysql->error
    ))
;

Then you use "..." token / ellipsis (documentation) in order to bind the array.

if ($statement) {
    $statement->bind_param($dibs, ...$cities);
    $statement->execute();

    $statement->close();
}
$mysql->close();

I know it kinda defeats the purpose of binding in order to escape (but at least it works good with a list of integers, i.e. IDs). If you see a way how to improve this approach, feel free to edit/comment.

I was having trouble with this too, and got it working with eval before finding out that most people are using call_user_func_array

$fields = array('model','title','price'); // fields in WHERE clause
$values = array( // type and value for each field
    array('s','ABCD-1001'),
    array('s','[CD] Test Title'),
    array('d','16.00')
);
$sql = "SELECT * FROM products_info WHERE "; // start of query
foreach ($fields as $current){ // build where clause from fields
    $sql .= '`' . $current . '` = ? AND ';
}
$sql = rtrim($sql,'AND '); // remove last AND 
$stmt = $db->prepare($sql);
$types = ''; $vals = '';
foreach ($values as $index => $current_val){ // build type string and parameters
    $types .= $current_val[0];
    $vals .= '$values[' . $index . '][1],';
}
$vals = rtrim($vals,','); // remove last comma
$sql_stmt = '$stmt->bind_param("' . $types . '",' . $vals . ');'; // put bind_param line together
eval($sql_stmt); // execute bind_param
$stmt->execute();
$stmt->bind_result($col1,$col2,$col3,$col4,$col5,$col6); // this could probably also be done dynamically in the same way
while ($stmt->fetch()){
    printf("%s %s %s %s %s %s\n", $col1,$col2,$col3,$col4,$col5,$col6);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!