2009-06-07 91 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扩展的实际经验,并且该项目是在其姊妹项目的用户的请求下创建的,因此可以从以下任何反馈中提供开发人员在生产中使用它将不胜感激。

免责声明 - 正如我所说,我做了这个扩展。