如何回应MySQLi预处理语句?

时间:2009-06-07 22:57:30

标签: 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();
}

我一直在查看此列表( 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对数据做了什么。但我想我可以通过这种方式快速查看所有数据是否存在并且位于正确的位置,并且与将变量手动拟合到查询中相比,它可以节省我一些时间 - 可以是很多变种的痛苦。

6 个答案:

答案 0 :(得分: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')

答案 1 :(得分: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 :(得分:4)

将其设置为die并输出最后执行的查询。错误处理应该为您提供有用的信息,您可以使用它们来修复查询。

答案 3 :(得分:2)

我最近更新了这个项目,包括作曲家集成,单元​​测试以及通过引用更好地处理接受参数(这需要更新到php 5.6)。


为了回应我在我创建的项目中收到的请求,使用PDO来解决同一问题,我在github上创建了mysqli的扩展,看起来它可以解决您的问题:

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;

将导致:

UPDATE registration SET name = 'Sue O\'reilly', email = 'sue.o@example.com' WHERE entryId = 5569

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

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

正如我在github项目中概述的那样,我没有使用mysqli扩展的任何实际经验,而且这个项目是应用户的要求创建的。姊妹项目,所以任何反馈都可以由开发人员在生产中使用它提供,我们将非常感激。

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

答案 4 :(得分:0)

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

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

并在日志文件中观察查询。 测试完成后,请注销:

sql> SET GLOBAL general_log = 'OFF';

答案 5 :(得分:-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();