2013-02-06 40 views
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 

在post數組被構造並分配給class屬性$ 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; 

}

預先感謝和讚賞。

回答

0

正如您所看到的,mysqli實際上不可用於準備好的語句。
所以,我建議你要麼使用PDO,要麼更好的是,一些智能庫可以在沒有準備好的情況下進行安全查詢。
有了這樣的功能將在一行

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

請注意,如果$陣列從不受信任的來源來了,你要過濾它的內容先出來寫成一個庫。

+0

+1爲常識的答案。將插入查詢過程切換到PDO並按預期工作。感謝常識。 – rwhite35

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(); 
} 

假設一切都與上面相同。

+0

你不需要任何約束力。只是'$ stmt-> execute($ array);'和PDO返回插入ID所有權利。 –

+0

嗯,讓我嘗試一下。但是,我沒有在其他地方優化輸入。我假設(輸入優化)過程丟失,如果我在$ array上執行綁定第一,是嗎? – rwhite35

相關問題