2009-06-07 49 views
40

我正在玩MySQLi,試圖弄清楚它是如何工作的。在我目前的項目中,我總是喜歡在編碼時回顯查詢字符串,只是爲了確保一切正確,並快速調試我的代碼。但是...我如何用MySQLi語句做好準備?如何回顯MySQLi準備好的語句?

例子:

$id = 1; 
$baz = 'something'; 

if ($stmt = $mysqli->prepare("SELECT foo FROM bar WHERE id=? AND baz=?")) { 
    $stmt->bind_param('is',$id,$baz); 
    // how to preview this prepared query before acutally executing it? 
    // $stmt->execute(); 
}

我已經經歷這個列表(http://www.php.net/mysqli),但沒有任何運氣。


編輯

啊,如果你從內庫MySQLi是不可能的,也許我會的東西堅持這樣的:

function preparedQuery($sql,$params) { 
    for ($i=0; $i<count($params); $i++) { 
    $sql = preg_replace('/\?/',$params[$i],$sql,1); 
    } 
    return $sql; 
} 

$id = 1; 
$baz = 'something'; 

$sql = "SELECT foo FROM bar WHERE id=? AND baz=?"; 

echo preparedQuery($sql,array($id,$baz)); 

// outputs: SELECT foo FROM bar WHERE id=1 AND baz=something 

遠非完美很明顯,因爲它仍然是相當冗餘—這是我想要阻止的一個問題,它也不能讓我知道MySQLi對數據做了什麼。但我想這樣我可以很快看到所有的數據是否存在並在正確的位置,並且與將手動變量手動納入查詢—相比,它可以節省我的一些時間,這可能會帶來許多變量的痛苦。

+3

哇,看起來不像有一種方法。悲傷......我希望我可以切換到mysqli,但我需要記錄所有爲歷史記錄運行的SQL語句。 – 2009-06-07 23:25:10

+1

你或許可以讓你的MySQL服務器記錄下它所接受的所有查詢 – 2009-06-07 23:34:51

+0

是的,這很有幫助,但我不想記錄SELECTS,它對調試沒有太大幫助,因爲每秒可能有很多查詢。 – 2009-06-07 23:43:00

回答

9

我不認爲你可以 - 至少不是你所希望的。您要麼必須自己構建查詢字符串並執行它(即不使用語句),要麼尋找或創建支持該功能的包裝器。我使用的一個是Zend_Db,這是我會怎麼做:

$id = 5; 
$baz = 'shazam'; 
$select = $db->select()->from('bar','foo') 
         ->where('id = ?', $id) 
         ->where('baz = ?', $baz); // Zend_Db_Select will properly quote stuff for you 
print_r($select->__toString()); // prints SELECT `bar`.`foo` FROM `bar` WHERE (id = 5) AND (baz = 'shazam') 
4

只需設置它的死去和輸出上次執行的查詢。錯誤處理應該爲您提供有意義的信息,您可以使用它來修復查詢。

6

我一直在努力與這一個過去。爲了解決這個問題,我編寫了一個基於SQL,標誌和變量爲我構建SQL的小函數。

//////////// Test Data ////////////// 
$_GET['filmID'] = 232; 
$_GET['filmName'] = "Titanic"; 
$_GET['filmPrice'] = 10.99; 

//////////// Helper Function ////////////// 
function debug_bind_param(){ 
    $numargs = func_num_args(); 
    $numVars = $numargs - 2; 
    $arg2 = func_get_arg(1); 
    $flagsAr = str_split($arg2); 
    $showAr = array(); 
    for($i=0;$i<$numargs;$i++){ 
     switch($flagsAr[$i]){ 
     case 's' : $showAr[] = "'".func_get_arg($i+2)."'"; 
     break; 
     case 'i' : $showAr[] = func_get_arg($i+2); 
     break; 
     case 'd' : $showAr[] = func_get_arg($i+2); 
     break; 
     case 'b' : $showAr[] = "'".func_get_arg($i+2)."'"; 
     break; 
     } 
    } 
    $query = func_get_arg(0); 
    $querysAr = str_split($query); 
    $lengthQuery = count($querysAr); 
    $j = 0; 
    $display = ""; 
    for($i=0;$i<$lengthQuery;$i++){ 
     if($querysAr[$i] === '?'){ 
      $display .= $showAr[$j]; 
      $j++; 
     }else{ 
      $display .= $querysAr[$i]; 
     } 
    } 
    if($j != $numVars){ 
     $display = "Mismatch on Variables to Placeholders (?)"; 
    } 
    return $display; 
} 

//////////// Test and echo return ////////////// 

echo debug_bind_param("SELECT filmName FROM movies WHERE filmID = ? AND filmName = ? AND price = ?", "isd", $_GET['filmID'], $_GET['filmName'], $_GET['filmPrice']); 

我也建立了一個小的在線工具來幫助。

Mysqli Prepare Statement Checker

2

我最近更新了這個項目,包括作曲家集成,單元​​測試和參照更好地處理接受的參數(這需要更新到PHP 5.6)。


在回答我對我寫來解決使用PDO同樣的問題項目接收到一個請求,我在GitHub上這似乎是它創造了一個擴展mysqli解決您的問題:

https://github.com/noahheck/E_mysqli

這是一組擴展本機mysqlimysqli_stmt類的類,允許您通過將綁定參數插入到準備好的查詢中來查看要在db服務器上執行的查詢的示例,然後爲您提供對得到的查詢字符串作爲stmt對象上一個新的屬性:

$mysqli = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName); 

$query = "UPDATE registration SET name = ?, email = ? WHERE entryId = ?"; 

$stmt = $mysqli->prepare($query); 

$stmt->bindParam("ssi", $_POST['name'], $_POST['email'], $_POST['entryId']); 

$stmt->execute(); 

echo $stmt->fullQuery; 

會導致:

UPDATE registration SET name = 'Sue O\'reilly', email = '[email protected]' WHERE entryId = 5569 

注意的是,在fullQuery值被轉義適當地考慮到角色的數據庫服務器上設置,這應該使這個功能適合於例如日誌文件,備份等。

有幾個使用它的警告,在Github項目的ReadMe中概述,但特別是對於開發,學習和測試,這應該提供一些有用的功能。

正如我在github項目中所概述的那樣,我沒有任何使用mysqli擴展的實際經驗,並且該項目是在其姊妹項目的用戶的請求下創建的,因此可以從以下任何反饋中提供開發人員在生產中使用它將不勝感激。

免責聲明 - 正如我所說,我做了這個擴展。