0

クラスインスタンスで定義されているように、ファクトリ(クラス)を使用してターゲットデータベーステーブルからフォームを表示しています。次に、送信時にクラスの新しいインスタンスを作成し、新しいレコードをデータベースに挿入します。$_POST キー名は、テーブルの列名と一致します。

私の問題は、変数がクラスインスタンスで決定されるときにバインドパラメーターを動的に割り当てることです。Reflections メソッドを使用するかインラインで使用するかに関係なく、次の結果が得られます。

 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;

}

よろしくお願いします。

4

2 に答える 2

0

常識に従って、プロセスを PDO に変更しました。期待どおりに動作します。もっと早くやるべきだった。残っている唯一の問題は、UI フィードバックです。挿入 ID を返したいのですが、MySQL は PDO の最後の挿入 ID を返しません。繰り返しになりますが、クラスは事前にテーブル構造を認識していないため、ハードコーディングはオプションではありません。回避策が必要です。何かご意見は?Heres は、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 に答える
0

ご覧のとおり、mysqli は準備済みステートメントでは実質的に使用できません。
したがって、PDO を使用するか、準備されたステートメントなしで安全なクエリを作成できるインテリジェントなライブラリを使用することをお勧めします。
このようなライブラリを使用すると、関数は1行で記述されます

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

$array が信頼できないソースからのものである場合は、最初にそのコンテンツを除外する必要があることに注意してください。

于 2013-02-06T14:19:14.390 に答える