2012-11-01 60 views
1

我有以下代碼:mysqli的綁定方法和call_user_func_array

function insertrow($tablename,$record){ 
     $columns = $this->gettablecol($tablename); 
     $types = $this->getbindtypestring($columns);  
     array_unshift($record, $types);            
     if(count($columns) && $types){    
      $query = 'INSERT INTO '.$tablename.' VALUES (?'.str_repeat(',?',count($columns)-1).')'; 
      if($stm = $this->linkid->prepare($query)){     
       $res = call_user_func_array(array(&$stm,"bind_param"), $params);      
       $stm->execute();      
       print_r($stm); 
       $stm->close();          
      } 
     } 
    } 

的$記錄陣列看起來是這樣的:

(
     [0] => sssisssssssssssi 
     [recordid] => TEST1 
     [recdate] => 2012-10-31 08:45:49 
     [lastmod] => 2012-10-31 08:45:49 
     [delflag] => 0 
     [cusname] => Dilbert 
     [address1] => 181 Somewhere 
     [address2] => 
     [city] => St. Petersburg 
     [state] => FL 
     [zipcode] => 33713 
     [telephone] => 8135551212 
     [faxnumber] => 8135551313 
     [webaddress] => 
     [taxid] => 260708780 
     [pinnumber] => 12345 
     [isactive] => 0 
) 

但是$ STM告訴我,有沒有數據:

mysqli_stmt Object 
(
    [affected_rows] => 0 
    [insert_id] => 0 
    [num_rows] => 0 
    [param_count] => 16 
    [field_count] => 0 
    [errno] => 2031 
    [error] => No data supplied for parameters in prepared statement 
    [sqlstate] => HY000 
    [id] => 1 
) 

看來$記錄數組在某種程度上是畸形的。任何洞察力將不勝感激。


嗨比爾,謝謝你的提醒。我接受了你的建議並將API切換到了PDO ......我必須承認我喜歡與它合作更容易;但是,我的問題還沒有解決。我改變了我的InsertRow方法是這樣的:

function insertrow($tablename,$record){   
     $this->connect(); 
     $columns = $this->gettablecol($tablename);  
     if(count($columns)){     
      $query = 'INSERT INTO '.$tablename.' VALUES (?'.str_repeat(',?',count($columns)-1).')'; 
      try{ 
       $stm = $this->linkid->prepare($query);     
       $stm->execute($record); 
      }catch(PDOException $e){ 
       $this->errormsg = $e.getMessage(); 
       $this.errhandler(); 
       exit(); 
      }   
     } 
    } 

當記錄看起來是這樣的:

Array 
(
    [recordid] => TEST1 
    [recdate] => 2012-11-01 09:12:50 
    [lastmod] => 2012-11-01 09:12:50 
    [delflag] => 0 
    [cusname] => Dilbert 
    [address1] => 181 Somewhere 
    [address2] => 
    [city] => St. Petersburg 
    [state] => FL 
    [zipcode] => 33713 
    [telephone] => 8135551212 
    [faxnumber] => 8135551313 
    [webaddress] => 
    [taxid] => 260708780 
    [pinnumber] => 12345 
    [isactive] => 0 
) 

我甚至複製$記錄的值到一個新的數組:

$newrec = array(); 
foreach($record as $row){ 
    $newrec = $row; 
} 

它看起來像這樣:

Array 
(
    [0] => TEST1 
    [1] => 2012-11-01 09:01:32 
    [2] => 2012-11-01 09:01:32 
    [3] => 0 
    [4] => Dilbert 
    [5] => 181 Somewhere 
    [6] => 
    [7] => St. Petersburg 
    [8] => FL 
    [9] => 33713 
    [10] => 8135551212 
    [11] => 8135551313 
    [12] => 
    [13] => 260708780 
    [14] => 12345 
    [15] => 0 
) 

並將它傳遞給$ stm-> execute($ newrec),但它不起作用,並沒有拋出異常。還有什麼我可以看看?

此時我已刪除傳遞$記錄陣列,只是硬編碼的值:

$stm->execute(array('TEST2','2012-10-10 00:00:00','2012-10-10 00:00:00',0,'1','2','3','4','5','6','7','8','9','0','11',0)); 

我仍然沒有得到插入到表即使兩個準備和執行回來的真正的記錄。

是否有必要將參數綁定到它們的特定數據類型?

回答

2

使用bind_param的困難是爲什麼我在開發可重用的數據庫訪問層時不喜歡使用Mysqli。它可以完成,但PHP的引用使它不必要地神祕。

解決的辦法,看到我在mysqli_prepare vs PDO

答案基本上,你通過數組必須引用數組,而不是標量的數組。

我發現在開發DBAL時使用PDO要容易得多。你不需要綁定任何東西。您只需將數組傳遞給PDOStatement::execute()即可。


回覆您的編輯:

我就是PDO是對您有所幫助。但這可能不是你最初的問題的根本原因。道歉,如果我的建議是一個瘋狂的追逐。但至少現在你正在使用PDO,所以這是一個人物建造的經歷。:-)

兩件事情,我注意到在你的代碼,但我不知道如果這些問題:

你添加了一些基於$柱陣列的數量參數佔位符,但是怎麼辦你知道這是與$記錄數組相同的計數?如果您在參數佔位符的數量與您提供的要執行的值的數量()之間不匹配,那麼這是一個錯誤。

您應該檢查:

if (count($columns) != count($record)) { 
    // report error 
} 

或者,你可以確保包括只在$記錄陣列按鍵提到列:

$columns_to_insert = array_intersect($columns, array_keys($record)); 

順便說(這不是一個錯誤,只是一個提示),我會生成這樣的參數佔位符序列,只是爲了避免字符串連接和錯過一個錯誤的風險:

join(",", array_fill(0, count($record), "?")) 
join(",", array_fill(0, count($record), "?")) 

我注意到的另一件事是,你不檢查execute()的返回值。如果它返回false則出現錯誤,您應該investigate the nature of the error

你在捕捉異常,但PDO的默認模式是而不是來拋出異常,但只是設置函數的返回值來指示錯誤。您可以以這種方式使用它,否則你必須明確地啓用例外拋出模式:

$this->linkid->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

即設置是全局的PDO連接的持續時間;您不必每次插入一行時都要這樣做。

+0

嗨比爾...更新了我的帖子。感謝您的信息。 – user1532602

+0

非常奇怪: '$ this-> linkid-> setAttribute(PDO :: ATTR_ERRMODE,PDO :: ERRMODE_EXCEPTION);' 打破我的代碼(導致內部500錯誤)。 – user1532602

+0

我假設$ this-> linkid是一個PDO對象。見http://php.net/manual/en/pdo.error-handling.php –