mysqli bind_param用于字符串数组

Mar*_*ark 6 php mysqli bindparam

我不能让这个工作.我现在已经花了很多时间.

这有效:

$mysqli = new mysqli("localhost", "root", "root", "db");
if(!$mysqli || $mysqli->connect_errno)
{
    return;
}
$query_str= "SELECT name FROM table WHERE city IN ('Nashville','Knoxville')";
$query_prepared = $mysqli->stmt_init();
if($query_prepared && $query_prepared->prepare($query_str))
{       
    $query_prepared->execute();
Run Code Online (Sandbox Code Playgroud)

但是我不能让它与这样的bind_param一起工作:

$query_str= "SELECT name FROM table WHERE city IN (?)";
$query_prepared = $mysqli->stmt_init();
if($query_prepared && $query_prepared->prepare($query_str))
{       
    $cities= explode(",", $_GET['cities']);
    $str_get_cities=  "'".implode("','", $get_cities)."'"; // This equals 'Nashville','Knoxville'

    $query_prepared->bind_param("s", $cities);
    $query_prepared->execute();
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

我也试过call_user_func_array,但似乎无法使语法正确.任何帮助将不胜感激!

编辑:我已经严格尝试了moskito-x的建议和大量的例子列在这里以及其他在SO和随机网站上,没有任何作品.我认为问题可能是PHP 5.4,这就是我的MAMP现在设置的.

mos*_*o-x 11

你不能用一个绑定两个变量question mark!

对于你绑定的每个变量,你需要一个 question mark

"bind_param"检查每个变量是否符合要求.之后,字符串值放在引号之间.

这不行.

"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')";
Run Code Online (Sandbox Code Playgroud)

一定是.

"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')";
Run Code Online (Sandbox Code Playgroud)

$query_prepared->bind_param引用字符串params一个接一个.
并且变量的数量和字符串类型的长度必须与语句中的参数匹配.

$query_str= "SELECT name FROM table WHERE city IN ('Nashville','Knoxville')";
Run Code Online (Sandbox Code Playgroud)

会变成

$query_str= "SELECT name FROM table WHERE city IN (?,?)";
Run Code Online (Sandbox Code Playgroud)

现在bind_param一定是

bind_param("ss",$arg1,$arg2)
Run Code Online (Sandbox Code Playgroud)

有了这个

$query_str= "SELECT name FROM table WHERE city IN (?)";
Run Code Online (Sandbox Code Playgroud)

bind_param

bind_param("s",$cities)
Run Code Online (Sandbox Code Playgroud)

你得到

$query_str= "SELECT name FROM table WHERE city IN ('Nashville,Knoxville')";
Run Code Online (Sandbox Code Playgroud)

这就是数组不起作用的原因.
这个事实的唯一解决方案是call_user_func_array

如果您初始化声明,则不必执行以下操作

$query_prepared = $mysqli->stmt_init();
if($query_prepared && $query_prepared->prepare($query_str)) {
Run Code Online (Sandbox Code Playgroud)

这是对的

$query_prepared = $mysqli->stmt_init();
if($query_prepared->prepare($query_str)) {
Run Code Online (Sandbox Code Playgroud)

如果您不想使用call_user_func_array
并且您只有少量参数
,则可以使用以下代码执行此操作.

[...]
$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();
  } 
 [...]
 }
Run Code Online (Sandbox Code Playgroud)

我建议你尝试一下call_user_func_array去.

寻找mysqli-stmt.bind-param的解决方案nick9v

  • 你建议使用`call_user_func_array`但你从来没有在这里显示如何做到这一点.= _ =" (15认同)

小智 5

像这样使用call_user_func_array:

$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;
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用,所有参数都必须是引用.所以你需要在`$ format ="siis";`中定义格式,然后在数组中使用`&$ format`.所有参数都必须是参考. (2认同)

You*_*nse 5

通常情况下,这个问题太老了,无法提供远程可靠的解决方案,但Google仍将访客发送到这里。所以这是2019年及以后的答案。

我将从Mysqli准备的语句中为IN子句添加多个值的方式进行解释:

  • 首先,我们需要创建一个字符串,其?标记与数组中元素的数量一样多。为此,我们将使用str_repeat()为此目的非常方便的功能。
  • 然后,必须将带有逗号分隔的问号的字符串添加到查询中。尽管它是一个变量,但在这种情况下它是安全的,因为它仅包含常量值
  • 那么该查询必须像其他任何查询一样准备
  • 那么我们将需要创建一个字符串,该字符串的类型要与bind_param()一起使用。注意,通常没有理由对绑定变量使用不同的类型-mysql会很乐意接受它们全部作为字符串。有边际案例,但极为罕见。对于日常使用,您可以始终保持简单,并在所有内容中使用“ s”。str_repeat()再次救援。
  • 那么我们需要将数组值绑定到该语句。不幸的是,您不能仅将其写为单个变量,像这样$stmt->bind_param("s", $array),只能使用标量变量bind_param()。幸运的是,有一个参数解包运算符可以完全满足我们的需要-将值数组发送到函数中,就好像它是一组不同的变量一样!
  • 其余的与往常一样-执行查询,获取结果并获取数据!

所以正确的示例代码是

$array = ['Nashville','Knoxville']; // our array
$in    = str_repeat('?,', count($array) - 1) . '?'; // placeholders
$sql   = "SELECT name FROM table WHERE city IN ($in)"; 
$stmt  = $mysqli->prepare($sql);
$types = str_repeat('s', count($array)); 
$stmt->bind_param($types, ...$array); // bind array at once
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$data = $result->fetch_all(MYSQLI_ASSOC); // fetch the data   
Run Code Online (Sandbox Code Playgroud)

尽管此代码很大,但与迄今为止在本主题中提供的任何其他合理的解决方案相比,它是无与伦比的。

  • 谢谢你!迄今为止最好、最干净的解决方案。我什至在第一次尝试时就根据自己的需要重写了它:) (6认同)
  • 我不明白你的答案的第一段。我不认为一个问题应该提供答案,他正在寻求你和其他人回答的答案。我所寻找的不是我需要添加多少问号,而是我已经有了。我找不到 bind_param 的正确解释,因为 php.net 文档似乎并不关心它。我想知道是否可以将数组作为参数传递给它。 (2认同)