多次调用 $stmt->bind_param

multiple calls to $stmt->bind_param

我正处于一种情况,我想构建一个代码,它以这种格式获取 $bindParam 变量:

$bindParams = [$type1 => $param1, $type2 => $param2, ... ]

我想构建一些代码,将这些参数动态添加到准备好的语句中。
这是我到目前为止构建的代码:

$mysql = new mysqli("localhost", "root", "", "db1");
$stmt = $mysql->prepare($sql);
foreach($bindParams as $type => $data) {
    $stmt->bind_param($type, $data);
}
$stmt->execute();
$result = $stmt->get_result();
// and after perhaps twiddling with the result set, but this is not the case .....

以你为例

$sql = "INSERT INTO table1 (name, age) VALUES (?,?);"

$bindParams = ["s" => "hello", "i" => 15] 

这并不总是这种结构,它可以更改为例如 $bindParams = ["s" => "hello", "i" => 15, "d" => 22.5]$sql 分别更改。

在编译器第一次前往 $stmt->bind_param($type, $data); firefox 后刷新此错误:

Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in D:\PHP\tr.php on line 23

我知道 PDO 支持,如前所述 here at the end of the page. 但也许如您所料,我不是 PDO 的粉丝,所以 ;)
我的另一个选择是使用 php 中可用的 eval() 解决方法,但这超出了我的想法。

还有其他方法吗?

我使用类似这样的东西来进行动态过程调用。

调用示例:

    $mapi = new MySQLIAPI($con);
    $mapi->BeginProc();
    $mapi->AddParameter("user", $usern, "s");
    $mapi->AddParameter("email", $email, "s");
    $mapi->AddParameter("passwd", $pwd, "s");
    $id = $mapi->CallProc("ij_create_user");
    $id = $id[0];

    if(isset($id['mysql_error']) || isset($id["error"])){
      return "error";
    }
    return $id["id"];

示例Class:

class MySQLIAPI
{
    private $con = null;
    private $Variables = null;
    private $values = null;
    private $types = null;
    private $vQu = null;
    private $stmt = null;
    function __construct($dbc)
    {
        $this->con = $dbc;
            $this->Variables = [];
        $this->values = [];
        $this->types = [];
        $this->vQu = [];
    }
    function BeginProc()
    {
        $this->stmt = $this->con->stmt_init(); // initialize statement
    }

    function AddParameter($key, $val, $type)
    {
        $this->Variables[] = "@" . $key;
        $this->values[]    = $val;
        $this->types[]     = $type;
        $this->vQu[]       = "?";
    }

    //KeyPair is v = the value, t = the type s or d
    function CallProc($Proc) {
      $out_var = null;

      $call = "";
      if(sizeof($this->values) > 0)
        $call = "CALL ".$Proc."(".implode(",", (array)$this->vQu).")";
      else
        $call = "CALL ".$Proc."()";

     if($this->stmt->prepare($call));//call stored procedure with database server session variable
     {
       if(sizeof($this->values) > 0) {
         $params = array_merge(array(implode("", $this->types)), $this->values);
         call_user_func_array(array($this->stmt, 'bind_param'), $this->refValues($params));
       }

       $this->stmt->execute();
       $result = $this->stmt->get_result();

       /* Error Checking */
       $mySQLiError = mysqli_stmt_error($this->stmt);
       if ($mySQLiError != "") {
         $this->resetStmt();
         $this->stmt->close();
         $this->stmt = null;
         return array('mysql_error' => $mySQLiError);
       }

       while ($row = $result->fetch_array(MYSQLI_ASSOC))
       {
         $out_var[] = $row;
       }
       $result->free();
       while($this->stmt->more_results())
       {
         $this->stmt->next_result();
       }

       $this->resetStmt();
       $this->stmt->close();
       $this->stmt = null;
     }

     return $out_var;
    }
    private function refValues($arr)
    {
        if (strnatcmp(phpversion(), '5.3') >= 0) //Reference is required for PHP 5.3+
            {
            $refs = array();
            foreach ($arr as $key => $value)
                $refs[$key] =& $arr[$key];
            return $refs;
        }
        return $arr;
    }
    private function resetStmt()
    {
        //Reset Params
        $this->Variables = array();
        $this->values    = array();
        $this->types     = array();
        $this->vQu       = array();
    }
}

遗憾的是 mysqli 不支持此功能。一遍又一遍地调用该函数会覆盖这些值,因此当您显然拥有更多参数时,您只能绑定一个参数。

有几种方法可以解决这个问题

  1. 切换到 PDO。您可以使用
  2. 对每个函数调用进行一次绑定
  3. 使用 call_user_func_array

    将参数绑定为一个聚合
    $sqltype = '';
    $sqldata = [];
    foreach($bindParams as $type => $data) {
        $sqltype .= $type;
        $sqldata[] = &$data; // MUST be a reference
    }
    array_unshift($sqldata, $sqltype); // prepend the types
    call_user_func_array([$stmt, 'bind_param'], $sqldata);
    

我遇到了同样的问题,找到了一个更简单的答案:

$array_of_values = array( "Brasil", "Argentina" );
$types = "ss";
$mysqli_stmt->bind_param( $types, ...$array_of_values );

这称为 "argument unpacking",从 PHP 5.6

开始可用