【问题标题】:Why successful results are not appearing from search bar in mysqli为什么mysqli的搜索栏中没有出现成功的结果
【发布时间】:2012-06-24 00:51:26
【问题描述】:

Mysqli 代码没有显示成功搜索的结果。该查询在语句方面是正确的,因为这是在 MYSQL 中测试的。但是当尝试使用 mysqli 时,我似乎无法在成功搜索后显示结果。我究竟做错了什么?在进行错误报告时我没有收到任何错误,并且查询中没有拼写错误。我不知道是不是因为查询需要在循环之外,或者我错误地绑定了参数或类似的东西,但代码曾经在旧的 mysql 代码中工作,但我无法让它在 mysqli 中工作(不能由于我的 PHP 版本,使用 PDO)

应用程序的 URL 是 here。如果您输入“AAD”,它会说它找不到任何结果,而实际上它应该这样做,因为数据库中有 5 行包含术语“AAD”

下面是表格代码:

<form action="previousquestions.php" method="get">
      <p>Search: <input type="text" name="questioncontent" value="<?php echo $questioncontent; ?>" onchange="return trim(this)" /></p>
      <p><input id="searchquestion" name="searchQuestion" type="submit" value="Search" /></p>
      </form>

下面是整个 mysqli 代码及其 cmets

//Get terms entered in the textbox    
$questioncontent = (isset($_GET['questioncontent'])) ? $_GET['questioncontent'] : '';

$searchquestion = $questioncontent;
$terms = explode(" ", $searchquestion);

//Start of query      
$questionquery = "
SELECT q.QuestionId, q.QuestionContent, o.OptionType, an.Answer, r.ReplyType,
FROM Answer an 
INNER JOIN Question q ON q.AnswerId = an.AnswerId
JOIN Reply r ON q.ReplyId = r.ReplyId 
JOIN Option_Table o ON q.OptionId = o.OptionId 

WHERE ";

$i=0;
//loop through each term
foreach ($terms as &$each) { 
$each = '%'.$each.'%';    
$i++;         

//if only 1 term entered then perform this LIKE statement       
if ($i == 1){         
$questionquery .= "q.QuestionContent LIKE ? ";     
} else {     
//If more than 1 term then add an OR statement    
$questionquery .= "OR q.QuestionContent LIKE ? ";    
} 
}  
//group terms by terms entered in chronilogical order                
$questionquery .= "GROUP BY q.QuestionId, q.SessionId ORDER BY "; $i = 0; foreach ($terms as $each) {     
$i++;      

//if multiple terms, then display results that contains all terms first, then start displaying other results by knocking off 1 term at a time                    
if ($i != 1)         
$questionquery .= "+";     
$questionquery .= "IF(q.QuestionContent LIKE ? ,1,0)"; 
} 

$questionquery .= " DESC "; 

//bind the parameters by the amount of terms there are      
$types = "";
for($i = 0; $i<sizeof($terms); $i++) {
$types .= "s";
}

//merge the parameters and the terms    
$eachterms = array_merge( array($types), $terms);

//prepare quert    
$stmt=$mysqli->prepare($questionquery);
//in array call all the parameters and its terms      
call_user_func_array(array($stmt, 'bind_param'), $eachterms);
//execute terms 
$stmt->execute();
//bind the result
$stmt->bind_result($dbQuestionContent); 


//display the results of the successful search
$output = "";
$output .= "
<table border='1' id='resulttbl'>
<tr>
<th class='questionth'>Question</th>
</tr>
";
while ($stmt->fetch()) {
$output .= "
<tr>
<td class='questiontd'>{$dbQuestionContent['QuestionContent']}</td>
</tr>";
}
$output .= "        </table>";

echo $output;

}

【问题讨论】:

    标签: php mysqli


    【解决方案1】:

    此错误消息的原因是$stmt 不是MySQLi_Stmt object。原因是您传递给$mysqli-&gt;prepare 的语句中有语法错误。

    "… q.QuestionContent LIKE '%'.$each.'%' "
    

    结果如下:

    … q.QuestionContent LIKE '%'.<value of each>.'%'
    

    这里的问题:. 不是 MySQL 中的字符串连接运算符(您需要使用+)并且$each 可能不是正确引用的 MySQL 字符串声明,因此它会导致有效表达。

    除此之外,将数据直接插入到语句中,您破坏了使用预准备语句的主要原因之一:将命令和数据彼此分开,这样数据就不会被误解为命令(即 SQL 注入)。

    所以不要直接插入字符串值,而是放置一个?。然后准备语句和bind the parameters给它执行:

    $questionquery = "
    SELECT q.QuestionId, q.QuestionContent, o.OptionType, an.Answer, r.ReplyType,
    FROM Answer an 
    INNER JOIN Question q ON q.AnswerId = an.AnswerId
    JOIN Reply r ON q.ReplyId = r.ReplyId 
    JOIN Option_Table o ON q.OptionId = o.OptionId 
    
    WHERE ";
    
    $paramTypes = '';
    $params = array();
    $i=0;
    //loop through each term
    foreach ($terms as $each) {
        $i++;
        //if only 1 term entered then perform this LIKE statement
        if ($i == 1){
            $questionquery .= "q.QuestionContent LIKE ? ";
        } else {
            //If more than 1 term then add an OR statement
            $questionquery .= "OR q.QuestionContent LIKE ? ";
        }
        $params[] = "%$each%";
        $paramTypes .= "s";
    }  
    //group terms by terms entered in chronilogical order                
    $questionquery .= "GROUP BY q.QuestionId, q.SessionId ORDER BY ";
    $i = 0;
    foreach ($terms as $each) {
        $i++;
        //if multiple terms, then display results that contains all terms first, then start displaying other results by knocking off 1 term at a time
        if ($i != 1) $questionquery .= "+";
        $questionquery .= "IF(q.QuestionContent LIKE ? ,1,0)";
        $params[] = "%$each%";
        $paramTypes .= "s"
    }
    $questionquery .= " DESC ";
    
    //prepare query
    $stmt=$mysqli->prepare($questionquery);
    //bind parameters
    call_user_func_array(array($stmt, 'bind_params'), array_merge(array($paramTypes), $params));
    //execute query
    $stmt->execute();
    

    哦,再说一遍:你真的应该看看fulltext search。它可以使整个手动查询构建过时:

    … WHERE MATCH (q.QuestionContent) AGAINST ("search terms" IN NATURAL LANGUAGE MODE)
    

    【讨论】:

    • 嗨,Gumbo 只是 2 个小问题,您在哪里显示了用于全文搜索的 f 行代码,我如何将那行代码放在查询中,我是否将它放在 WHERE 子句旁边然后为 2 个 lIKE 语句添加 AND 子句?此外,在测试您的代码时,它会在提交搜索声明 Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'mysqli_stmt::bind_params' was given in ... on line 98 后向我显示警告。赞成的答案
    • @user1421767 我没有测试查询;由于语法错误,准备它仍然可能失败。如果您想改用全文搜索,请先阅读链接页面。它将解释所有必要的事情。
    • 我会阅读该文档,但要替换“匹配(q.QuestionContent)反对(自然语言模式中的“搜索词”)的 LIKE 语句?还是我还需要使用 LIKE 语句?
    • @user1421767 不,单个MATCH … AGAINST … 将替换您所有的… LIKE … 表达式。
    • 所以我的查询应该是这样的:$questionquery = " SELECT * FROM Answer an INNER JOIN Question q ON q.AnswerId = an.AnswerId JOIN Reply r ON q.ReplyId = r.ReplyId JOIN Option_Table o ON q.OptionId = o.OptionId WHERE MATCH (q.QuestionContent) AGAINST ("$each" IN NATURAL LANGUAGE MODE ";(使用 $each 匹配术语)然后使用 group by、orderby 和 IF 结束查询
    【解决方案2】:

    更改语句:

    $questionquery .= "IF(q.QuestionContent LIKE '%'.$each.'%' ,1,0)";
    $questionquery .= "q.QuestionContent LIKE '%'.$each.'%' ";
    $questionquery .= "OR q.QuestionContent LIKE '%'.$each.'%' ";
    

    对此(分别):

    $questionquery .= "IF(q.QuestionContent LIKE '%" . $each . "%' ,1,0)";
    $questionquery .= "q.QuestionContent LIKE '%" . $each . "%' ";
    $questionquery .= "OR q.QuestionContent LIKE '%" . $each . "%' ";
    

    另外,我认为您需要为您的 $stmt 变量执行此操作:

    $stmt = $mysqli->stmt_init();
    $stmt->prepare($questionquery);
    //execute query
    $stmt->execute();
    

    【讨论】:

    • @Gumbo 这不是php.net上的定义吗
    • @T-ShirtDude 我只是在您的应用程序中测试您的答案。我会在 5 分钟内告诉你发生了什么:)
    • prepared statements 的一个原因是为了将命令和数据分开。但是在这里你又把它弄混了。
    • @T-ShirtDude 好的,它已经删除了致命错误,但如果我回滚到上一个问题,它会导致搜索栏无法正常工作。有一个小问题,如果它是一个成功的搜索,它没有显示搜索结果,你对此有什么想法吗?我正在更新代码,请给我 2 分钟
    • 我已经更新了代码,我没有包含这个代码:$stmt = $mysqli-&gt;stmt_init();,因为它没有这个就删除了错误。我确实在我的应用程序中尝试了那行代码,但它并没有改变显示搜索结果的结果
    猜你喜欢
    • 2020-07-09
    • 2021-09-25
    • 2023-04-04
    • 2018-11-06
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多