53

我现在正在玩 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 对数据做了什么。但我想这样我可以快速查看所有数据是否存在并且在正确的位置,与手动将变量拟合到查询中相比,它会节省一些时间——这对于许多变量来说可能会很痛苦。

4

6 回答 6

12

我不认为你可以——至少不是你希望的那样。您要么必须自己构建查询字符串并执行它(即不使用语句),要么寻找或创建支持该功能的包装器。我使用的是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')
于 2009-06-07T23:26:48.920 回答
9

我过去一直在努力解决这个问题。所以为了解决这个问题,我编写了一个小函数来基于 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 准备语句检查器

于 2012-07-25T20:19:51.100 回答
6

我最近更新了这个项目,包括作曲家集成、单元测试和更好地处理通过引用接受参数(这需要更新到 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 = 'sue.o@example.com' WHERE entryId = 5569

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

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

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

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

于 2014-07-26T17:46:03.363 回答
3

只需将其设置为死并输出最后执行的查询。错误处理应该为您提供有意义的信息,您可以使用这些信息来修复您的查询。

于 2009-06-08T01:00:25.533 回答
-1

您可以在 mysql 服务器上打开日志查询。只需执行命令:

sql> SHOW VARIABLES LIKE "general_log%";
sql> SET GLOBAL general_log = 'ON';

并观察日志文件中的查询。测试后关闭日志:

sql> SET GLOBAL general_log = 'OFF';
于 2018-08-20T15:48:02.373 回答
-1

var_dump()至少可以用来获取有关 mysqli_stmt 的更多信息:

  $postmeta_sql = "INSERT INTO $db_new.wp_postmeta (post_id, meta_key, meta_value) VALUES (?, ?, ?)";
  $stmt = $new_conn->prepare($postmeta_sql);
  $stmt->bind_param("sss", $post_id, $meta_key, $meta_value);
  echo var_dump($stmt);
  $stmt->execute();
  $stmt->close();
于 2020-11-19T22:01:32.737 回答