0

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

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

 Warning: mysqli_stmt::bind_param() [mysqli-stmt.bind-param]: Number of elements in type definition string doesn't match number of bind variables

在构建后数组并分配给类属性 $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;

}

在此先感谢并非常感谢。

4

2 回答 2

0

如您所见,mysqli 实际上无法用于准备好的语句。
因此,我建议您使用 PDO,或者更好的是,一些智能库可以在没有准备好的语句的情况下进行安全查询。
有了这样一个库,您的函数将写在一行中

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

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

于 2013-02-06T14:19:14.390 回答
0

根据常识,将流程更改为 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();
 }

假设其他一切都与上述相同。

于 2013-02-06T19:19:38.037 回答