如何回应MySQLi预处理语句?

Ale*_*lec 46 php 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();
}
Run Code Online (Sandbox Code Playgroud)

我一直在浏览这个清单(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
Run Code Online (Sandbox Code Playgroud)

显然远非完美,因为它仍然是多余的 - 我想要阻止的东西 - 而且它也没有让我知道MySQLi对数据做了什么.但我想我可以通过这种方式快速查看所有数据是否存在并且位于正确的位置,与将变量手动拟合到查询中相比,它将节省一些时间 - 这可能是许多变量的痛苦.

kar*_*m79 10

我认为你不能 - 至少不是你希望的方式.您可能需要自己构建查询字符串并执行它(即不使用语句),或者寻找或创建支持该功能的包装器.我使用的是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')
Run Code Online (Sandbox Code Playgroud)

  • 对复杂准备好的语句的重大监督,您可能希望将其复制并粘贴到查询窗口中进行检查/测试。字符串显然在那里_某处_,为什么不给我们一个只读的“statement”属性呢? (2认同)

小智 7

我过去一直在努力解决这个问题.为了解决这个问题,我编写了一个基于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']);
Run Code Online (Sandbox Code Playgroud)

我还建立了一个小的在线工具来帮助.

Mysqli准备声明检查器


Noa*_*eck 5

我最近更新了这个项目以包含 Composer 集成、单元测试并更好地处理通过引用接受参数(这需要更新到 php 5.6)。


为了响应我在创建的一个项目上收到的请求,我使用 来解决同样的问题PDO,我mysqli在 github 上创建了一个扩展,它似乎解决了您的问题:

https://github.com/noahheck/E_mysqli

这是一组扩展本机mysqlimysqli_stmt类的类,允许您通过将绑定参数插入到准备好的查询中来查看要在数据库服务器上执行的查询示例,然后让您访问结果查询字符串作为新属性在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;
Run Code Online (Sandbox Code Playgroud)

会导致:

UPDATE registration SET name = 'Sue O\'reilly', email = 'sue.o@example.com' WHERE entryId = 5569
Run Code Online (Sandbox Code Playgroud)

请注意,考虑到 db 服务器上的字符集,fullQuery 中的值被适当地转义,这应该使此功能适用于例如日志文件、备份等。

使用它有一些注意事项,在 github 项目的自述文件中概述,但是,特别是对于开发、学习和测试,这应该提供一些有用的功能。

正如我在 github 项目中概述的那样,我没有使用该mysqli扩展的任何实践经验,并且该项目是应其姊妹项目用户的要求创建的,因此在生产中使用此扩展的开发人员可以提供任何反馈将不胜感激。

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