【问题标题】:How to perform a LIKE query using multiple keywords from search field using mysqli prepared statement如何使用 mysqli 准备语句使用搜索字段中的多个关键字执行 LIKE 查询
【发布时间】:2018-06-28 16:57:27
【问题描述】:

这个问题和this previously asked question类似,只是我用的是mysqli而不是PDO。

我这样执行查询:

$word=preg_split('/[\s]+/',$terms);
$totalwords=count($word);

$terms 是从 GET 进一步向上获取的

$sql="SELECT title,content FROM articles WHERE (title LIKE CONCAT('%',?,'%') OR (content LIKE CONCAT('%',?,'%'))";

for(i=1;$i<$totalwords;$i++){
  $sql.=" OR (title LIKE CONCAT('%',?,'%') OR (content LIKE CONCAT('%',?,'%'))";
}

$stmt=$conn->prepare($sql);
foreach($word as $key => $keyword){
  $term=$keyword;
  $stmt->bind_param('ss',$term,$term);
}
$stmt->execute;
$stmt->store_result;

如果我在搜索表单中输入一个单词,我会得到正确的结果,但是,如果我输入多个单词,则根本不会得到任何结果。

所以我添加了一个print_r($sql); 来查看发送到数据库的内容,这是我在一个学期内得到的(效果很好):

SELECT title,content FROM articles WHERE (title LIKE CONCAT('%',?,'%') OR content LIKE CONCAT('%',?,'%'));

这就是我得到多个单词的结果(即使它应该返回也不返回结果):

SELECT title,content FROM articles WHERE (title LIKE CONCAT('%',?,'%') OR content LIKE CONCAT('%',?,'%')) OR (title LIKE CONCAT('%',?,'%') OR content LIKE CONCAT('%',?,'%'));

似乎一切正常,所以我打开了我的 mysql 日志,发现单字查询出现了,但多字查询不存在。

所以我添加了print_r($stmt);,然后我得到Commands out of sync; you can't run this command now 用于多词查询。

我做错了什么?

【问题讨论】:

  • 你可以做CONCAT(title, ' ', content) LIKE CONCAT('%',?,'%')然后你只需要一个绑定,而不是两个。我希望收到有关占位符数量与参数数量不匹配的错误消息。上一个问题是使用支持命名参数的 PDO。 IMO 的 Mysqli 的绑定方式很麻烦。
  • 不相关,但我不会创建 $term 变量,只需使用 $keyword... 或仅使用 =&gt; $term
  • @user3783243 感谢您指出绑定参数与占位符的不匹配。我根本没有注意到这一点。我在下面提供了一个解决方案,因为尚未提供。
  • 如果它解决了您的问题,我可以将该评论移至答案。我不确定它是否会/不会,我没有测试它。
  • 听起来不错。

标签: php search mysqli


【解决方案1】:

正如 user3783243 在上面的 cmets 中所说,我的占位符和参数不匹配。所以为了解决这个问题,我做了以下事情(这会很草率,因为我是 PHP 新手,但如果有人可以为我清理它,我会奖励答案)。

首先你必须为类型参数创建一个字符串(我的都是字符串,所以这很简单,如果你有不同的类型,你可以运行一个条件语句)。由于我在 SQL 中为每个条目使用两个占位符,因此每次迭代都将包含两个 s

$typeparam='';
foreach($word as $key => $value){
  $typeparam.='ss';
}

然后创建一个新数组将类型和值放在一起(同样,由于每个参数有两个占位符,我只是将 $word 两次添加到数组中):

$bindpars=array();

$bindpars[]=&$typeparam;
foreach($word as $key => $value){
  $bindpars[]=&$word[$key];
  $bindpars[]=&$word[$key];
}

最后使用call_user_func_array绑定参数:

call_user_func_array(array($stmt,'bind_param'),$bindpars);

所以我的问题中的代码现在看起来像这样:

$word=preg_split('/[\s]+/',$terms);
$totalwords=count($word);

$sql="SELECT title,content FROM articles WHERE (title LIKE CONCAT('%',?,'%') OR (content LIKE CONCAT('%',?,'%'))";

for(i=1;$i<$totalwords;$i++){
  $sql.=" AND (title LIKE CONCAT('%',?,'%') OR (content LIKE CONCAT('%',?,'%'))";
}

$stmt=$conn->prepare($sql);

$typeparam='';
foreach($word as $key => $value){
  $typeparam.='ss';
}

$bindpars=array();

$bindpars[]=&$typeparam;
foreach($word as $key => $value){
  $bindpars[]=&$word[$key];
  $bindpars[]=&$word[$key];
}

call_user_func_array(array($stmt,'bind_param'),$bindpars);

$stmt->execute;
$stmt->store_result;

【讨论】:

    猜你喜欢
    • 2012-10-24
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多