如何回应MySQLi准备好的声明?

我正在玩MySQLi,试图弄清楚它是如何工作的。 在我当前的项目中,我总是喜欢在编码时回显一个查询string,只是为了确保一切正确,并快速debugging我的代码。 但是…我怎么能用一个准备好的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对数据做什么的想法。 但我想这样我可以很快看到所有的数据是否存在,并在正确的位置,相比于手动将variables适配到查询中,这会节省一些时间 – 这可能是一个很多变数的痛苦。

我不认为你可以 – 至less不是你所希望的。 你要么必须自己构build查询string并执行它(即不使用语句),要么找出或创build支持该function的包装器。 我使用的是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') 

过去我一直在与这个挣扎。 为了解决这个问题,我编写了一个基于SQL,标志和variables为我构buildSQL的小函数。

 //////////// 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']); 

我也build立一个小的在线工具来帮助。

Mysqli准备语句检查器

只要将其设置为死亡并输出上次执行的查询。 error handling应该给你有意义的信息,你可以用它来修复你的查询。

我最近更新了这个项目,包括composer php集成,单元​​testing,并更好地处理通过引用接受参数(这需要更新到PHP 5.6)。


为了回应我为了解决使用PDO解决相同问题而创build的项目的要求,我在github上创build了一个mysqli的扩展,它似乎解决了您的问题:

https://github.com/noahheck/E_mysqli

这是一组扩展本地mysqlimysqli_stmt类的类,允许您通过将绑定参数插入到准备好的查询中来查看要在db服务器上执行的查询的示例,然后将访问所得到的查询string作为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 = 'sue.o@example.com' WHERE entryId = 5569 

请注意,fullQuery中的值会在考虑到db服务器上的字符集的情况下进行适当的转义,这会使该function适用​​于例如日志文件,备份等。

在github项目的ReadMe中有一些使用这个的警告,但是特别是对于开发,学习和testing,这应该提供一些有用的function。

正如我在github项目中所概述的那样,我没有任何使用mysqli扩展的实际经验,而且这个项目是在姊妹项目的用户的请求下创build的,所以任何可以由devs提供的反馈生产将不胜感激。

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