【问题标题】:MySql search using LIKE clause not working使用 LIKE 子句的 MySql 搜索不起作用
【发布时间】:2019-04-30 12:00:59
【问题描述】:

我正在尝试使用 php5 pdo 和 mysql 实现搜索。我要做的是在我的表“帖子”中搜索给定的一组关键字,并返回包含“标题”列中任何给定关键字的记录。但即使我给出我知道表中存在的关键字,它也不会返回任何结果集。我使用排序规则“utf8mb4_unicode_ci”。这是我的代码:

 <?php
if($_SERVER['REQUEST_METHOD']=='POST'){
$charset="utf8mb4";
$dsn="mysql:host=$host;dbname=$db;charset=$charset";
$opt=[  PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
      PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION];
$pdo=new PDO($dsn,$user,$pass,$opt);
$keywords=$_POST['keywords'];
$keywordArray=explode(' ',$keywords);
$n=count($keywordArray);
$query="SELECT * FROM posts WHERE title LIKE ?";
$keywordArray[0]="'%".$keywordArray[0]."%'";
for($i=1;$i<$n;$i++){
  $keywordArray[$i]="'%".$keywordArray[$i]."%'";
  $query=$query." OR title LIKE ?";
}
$query=$query." LIMIT 50;";
     echo $query;
$stmt=$pdo->prepare($query);
$stmt->execute($keywordArray);
$res=$stmt->fetchAll();
echo "<br><h1>SEARCH RESULTS:</h1><br><ul>";
if($res){
foreach($res as $row){
  echo "<li>".$row['date']."<a href=\"viewpost.php?postid=".$row['id']."\">".$row['title']."</a></li><br>";
}
}
else{
echo "<h2 style=\"color:red;\">No results!</h2>";
}
echo "</ul></div>";
}
?>

它在控制台内工作。

SELECT * FROM posts WHERE title LIKE '%hit%' OR title LIKE '%fifa%';

返回两行。但是使用表单搜索“hit fifa”会返回零行。

【问题讨论】:

  • 那个?因为 LIKE 模式无效...使用正确格式的 LIKE 模式。
  • 您能指出我的模式中的错误吗?抱歉,我已经用谷歌搜索了好几次,但我找不到解决方案。
  • @Werner 我认为你混淆了?这是一个参数的占位符,它实际上是 LIKE 表达式的一部分。
  • @abhiramsanthosh 我的评论是针对维尔纳的,而不是你。我想你知道你在做什么?关于您的实际问题,我已经在下面写了一个答案。
  • @Werner 没问题。只是一个小点 - PDO 可以在有或没有参数化查询的情况下使用。和 mysqli 接受?作为占位符。您错过的不是一般 PDO 的使用……而是参数化查询的使用。

标签: php mysql sql pdo sql-like


【解决方案1】:

由于您使用的是准备好的语句,因此您不需要在表达式周围加上单引号。更改您的代码,删除这些引号,以

$query="SELECT * FROM posts WHERE title LIKE ?";
$keywordArray[0]="%".$keywordArray[0]."%";
for($i=1;$i<$n;$i++){
  $keywordArray[$i]="%".$keywordArray[$i]."%";
  $query.=" OR title LIKE ?";
}

它将引号视为参数内值的一部分。所以你最终会得到类似的 SQL

SELECT * FROM posts WHERE title LIKE '\'%Something%\''

显然这不匹配,因为在大多数情况下,数据库中的值在开头和结尾不会有单引号。

随着更改,它应该像这样转换为 SQL

SELECT * FROM posts WHERE title LIKE '%Something%'

这是因为参数化过程会自动为您处理引用和转义作业 - 这是它防止 SQL 注入攻击的一种方式(顺便提一下,防止由错误/未转义的引号引起的语法错误)。


附:如果向此代码提交了一个请求,但根本没有提供任何关键字,那么代码将崩溃,因为它假定$keywordArray[0] 中始终存在一个值。考虑修改它以验证是否提供了关键字,或者只是循环整个数组,如果没有提交关键字,则根本不向查询添加 WHERE 子句。

【讨论】:

  • 它成功了,感谢您的详细回答。关于 no 关键字的情况,我在 html 输入标签内写了 'required',这会有帮助吗?
  • 只要没有人弄乱客户端代码(很简单,如果你知道怎么做的话),或者决定使用 PostMan 等其他工具直接向你的服务器发送 HTTP 请求.客户端验证有利于用户体验,但您不能依赖它来始终检查您的输入。服务器端检查也必须始终进行(事实上,它们应该是您编写的第一个检查,然后如果有时间,您可以稍后添加客户端的东西)。
  • 可耻的是我没有注意到这一点,因为即使我玩的是 post 变量和 burpsuit 的请求。会这样做。
猜你喜欢
  • 2011-04-09
  • 2013-07-20
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
相关资源
最近更新 更多