Php 在类实例中将表单字段名传递给绑定参数

Php 在类实例中将表单字段名传递给绑定参数,php,reflection,binding,prepared-statement,Php,Reflection,Binding,Prepared Statement,我使用一个工厂(类)来表示目标数据库表中的表单,正如在类实例中定义的那样。然后在提交时,创建该类的新实例,然后将新记录插入数据库$_POST键名称与表列名匹配 我的问题是在类实例中确定变量时动态分配绑定参数。无论我使用反射方法还是内联方法,我都会得到以下结果 Warning: mysqli_stmt::bind_param() [mysqli-stmt.bind-param]: Number of elements in type definition string doesn't match

我使用一个工厂(类)来表示目标数据库表中的表单,正如在类实例中定义的那样。然后在提交时,创建该类的新实例,然后将新记录插入数据库$_POST键名称与表列名匹配

我的问题是在类实例中确定变量时动态分配绑定参数。无论我使用反射方法还是内联方法,我都会得到以下结果

 Warning: mysqli_stmt::bind_param() [mysqli-stmt.bind-param]: Number of elements in type definition string doesn't match number of bind variables
在构造post数组并将其分配给类属性$array之后,将在子类中调用以下方法

  private function addrecord($array,$tbl,$_conn){

   //define field name array for query statement
   foreach ($array as $key=>$value){
   $keyarr[]=$key;
   }

//BUILD THE QUERY STATEMENT
$query = "INSERT INTO $tbl SET ";
  foreach ($keyarr as $key){
    $query .= ($key."=?, ");    //clone and add next element
  }
$query = rtrim($query,", ");    //remove EOL whitespace and comma
//done

 /*
//Hard code bind parameters works as expected
if (self::$_conn = new mysqli(DB_HOST,DB_UNAME,DB_UPWORD,DB_NAME)){
$stmt=self::$_conn->prepare($query);
   $stmt->bind_param("sssss",$array['user_id'],$array['user_name'],$array['user_email'],$array['user_date'],$array['user_active']);
$stmt->execute();
$insertid=$stmt->insert_id;
$stmt->close();
echo "The record was created with id ".$insertid;
}
 */

  //Tried re assigning post array as reference
  //same error as just passing $array
  //$array = $this->refValues($array);

 //Binding params using Reflections, same error 
 self::$_conn = new mysqli(DB_HOST,DB_UNAME,DB_UPWORD,DB_NAME);
 $stmt   = self::$_conn->prepare($query);
 $ref    = new ReflectionClass('mysqli_stmt');
 $method = $ref->getMethod("bind_param");
 $method->invokeArgs($stmt,$array);
 $stmt->execute();
 $stmt->close();
 self::$_conn->close();
 }

//Pass By Reference required for PHP 5.3+, dev server 5.3.17
function refValues($arr){
   if (strnatcmp(phpversion(),'5.3') >= 0){
   $refar = array();
    foreach($arr as $key => $value)
      $refar[$key] = &$arr[$key];
      return $refar;
    }
   return $arr;
}


提前感谢,非常感谢。

正如您所看到的,mysqli实际上无法使用预先准备好的语句。
因此,我建议您要么使用PDO,要么更好,使用一些智能库,无需准备好声明即可进行安全查询。
有了这样一个库,您的函数将被写在一行中

private function addrecord($array,$tbl){
    $this->conn->query("INSERT INTO ?n SET ?u", $tbl, $array);
}

请注意,如果$array来自不受信任的源,您必须首先过滤掉它的内容。

根据常识,将过程更改为PDO。一切正常。我应该早点做。剩下的唯一问题是UI反馈。希望返回一个插入id,但是MySQL不会返回PDO的最后一个插入id。再说一遍,这个类事先不知道表的结构,所以硬编码是不可取的。需要一个解决办法。有什么想法吗?下面是使用PDO的新插入过程

 try{
   self::$_conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.'', DB_UNAME, DB_UPWORD);
   $stmt = self::$_conn->prepare($query);

   $arcount=count($array);  //set number of bindParam loops
     foreach($array as $key=>$value){
   $stmtarr[]=$value;   //convert assoc to numerated array
}
 //re index array so increment will match up with placeholder position
 $stmtarr = array_combine(range(1, count($stmtarr)), array_values($stmtarr));

 for($i=1;$i<=$arcount;$i++){ //bind variable, one for each placeholder, 
$stmt->bindParam($i,$stmtarr[$i]);
 }
 $stmt->execute();

 } catch (PDOException $e){
print "Error: ".$e->getMessage()."<br>";
die();
 }
试试看{
self:$_conn=new PDO('mysql:host='.DB_host';dbname='.DB_NAME'',DB_UNAME,DB_UPWORD);
$stmt=self::$\u conn->prepare($query);
$arcount=count($array);//设置bindParam循环的数量
foreach($key=>$value的数组){
$stmtarr[]=$value;//将关联转换为数值数组
}
//重新索引数组,使增量与占位符位置匹配
$stmtar=array_combine(范围(1,计数($stmtar)),array_值($stmtar));
对于($i=1;$ibindParam($i,$stmtar[$i]);
}
$stmt->execute();
}捕获(PDO$e){
打印“错误:”$e->getMessage()“
”; 模具(); }

假设其他所有内容都与上面相同。

+1表示常识性答案。将插入查询过程切换到PDO并按预期工作。感谢常识。您不需要绑定。只需执行($array)并且PDO返回insert id好的。嗯,让我试试。但是,我不会在其他地方优化输入。我假设如果我在没有out binding的情况下首先在$array上执行,(输入优化)过程会丢失,对吗?