繁体   English   中英

PHP MySQLi准备/绑定where子句

[英]PHP MySQLi prepare/bind where-clause

出于节省的原因,我尝试使用mysqli :: prepare(),但是如果我尝试使用“?”准备在哪条子句 mysqli :: bind_params()失败(没有任何错误):

调用查询函数:

$messages = query('SELECT * FROM messages WHERE (receiverID=? AND receiverType=?) OR (senderID=? AND senderType=?) ORDER BY date DESC', false, '', (int)$_SESSION['ID'], (string)$_SESSION['mode'][0], (int)$_SESSION['ID'], (string)$_SESSION['mode'][0]);

查询功能:

function query($sql, $fetch, $error, ...$values) {
    global $language; //get translations
    global $mysqli; //get database
    $returnResult = (strtolower(substr(trim($sql), 0, 6)) === 'select'); //check for select ---> retrun result
    if(!empty($error)) $error .= '\n'; //next line after error message (styling / readability)
    $stmt = $mysqli->prepare($sql) or back($error.$language['mysqliErrorPrepare'].$stmt->error); //prepare
    foreach($values as $value) { //go through all params
        $stmt->bind_param((is_string($value)?'s':(is_float($value)?'d':(is_int($value)?'i':'b'))), $value) or back($error.$language['mysqliErrorBind'].$stmt->error); //bind param
    }
    $stmt->execute() or back($error.$language['mysqliErrorExecute'].$stmt->error); //execute
    if($returnResult) $result = $stmt->get_result() or back($error.$language['mysqliErrorGetResult'].$mysqli->error); //get result if necessary
    $stmt->close(); //close
    if($returnResult AND $fetch) $result = $result->fetch_assoc()or back($error.$language['mysqliErrorFetch'].$mysqli->error); //fetch if required
    return ($returnResult?$result:true); //return result / true
}

问题:

  • 为什么会失败?
  • 我可以准备在哪儿吗?

谢谢! -介意

是不是因为任何活动数据库都没有调用它?

尝试$db->query(); 如下:

$messages = $db->query('SELECT * FROM messages WHERE (receiverID=? AND receiverType=?) OR (senderID=? AND senderType=?) ORDER BY date DESC', false, '', (int)$_SESSION['ID'], (string)$_SESSION['mode'][0], (int)$_SESSION['ID'], (string)$_SESSION['mode'][0]);

这不起作用的原因是我试图一个一个地绑定参数,而mysqli :: bind_param()希望一次接收所有参数 因此,MySQL只有一个参数,但是要使用4个问号,这显然会导致错误。

动态绑定多个参数的“正确”方法是:

if(count($paramValues) > 0) {
    $paramTypes = '';
    $paramBindValues = [&$paramTypes];
    foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($paramValues), RecursiveIteratorIterator::LEAVES_ONLY) as $paramValue) {
        $paramTypes .= (is_string($paramValue)?'s':(is_float($paramValue)?'d':(is_int($paramValue)?'i':'b')));
        $paramBindValues[] = &$paramValue;
        unset($paramValue);
    }
    if(!$stmt->bind_param(...$paramBindValues))
        throw new Error($sql);
}

但是请注意,这也破坏了准备好的语句的可重用性,因此可能具有次佳的性能。

一个例子:

foreach($users as $user) {
   //This prepares the statement everytime.
   $info = query('SELECT info FROM users WHERE ID=?', true, '', $user['ID']);
}

//This only prepares the statement once.
$stmt = $mysqli->prepare('SELECT info FROM users WHERE ID=?');
foreach($users as $user) {
    $stmt->bind_params('i', $user['ID']);
    $stmt->execute();
    $info = $stmt->get_result()->fetch_assoc();
}
$stmt->close();

感谢@Sean指出mysqli :: bind_params()一次接受所有参数并提供示例。

希望这可以帮助。 -思想

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM