PHP PDO 准备语句——MySQL LIKE 查询

Posted

技术标签:

【中文标题】PHP PDO 准备语句——MySQL LIKE 查询【英文标题】:PHP PDO prepared statement -- MySQL LIKE query 【发布时间】:2010-12-19 16:13:51 【问题描述】:

我正在尝试通过 php 的 PDO 类(mysql 驱动程序)进行搜索。我有以下查询与 MySQL 客户端一起使用(更改表名以保护无辜者):

SELECT    hs.hs_pk, 
          hs.hs_text, 
          hs.hs_did, 
          hd.hd_did, 
          hd.hd_text, 
          hv.hv_text, 
          hc.hc_text 
FROM      hs 
LEFT JOIN hd 
 ON       hs.hs_did = hd.hd_did 
LEFT JOIN hd 
 ON       hd.hd_vid = hv.hv_id 
LEFT JOIN hc 
 ON       hd.hd_pclass = hc.hc_id
WHERE     hs.hs_text LIKE "%searchTerm%"
LIMIT 25;

无论我使用什么搜索词,这都像一个魅力。但是,当我转向 php 时,我无法让它返回任何东西。我尝试了几种看起来合乎逻辑的不同语法,但我没有尝试过。这是我现有的代码:

$handle = fopen('/foo/bar/test.log', 'w+');
fwrite($handle, "doSearch, with search term: $searchTerm\n");
$sql = 
'SELECT   hs.hs_pk, 
          hs.hs_text, 
          hs.hs_did, 
          hd.hd_did, 
          hd.hd_text, 
          hv.hv_text, 
          hc.hc_text 
FROM      hs 
LEFT JOIN hd 
 ON       hs.hs_did = hd.hd_did 
LEFT JOIN hd 
 ON       hd.hd_vid = hv.hv_id 
LEFT JOIN hc 
 ON       hd.hd_pclass = hc.hc_id
WHERE     hs.hs_text LIKE :searchTerm
LIMIT 25';

try 
 $dbh = new PDO('mysql:host=localhost;dbname=awdb', "user", "password");
 fwrite($handle, "connected to DB\n");
 $prep = $dbh->prepare($sql);
 $ret = $prep->execute(array(':searchTerm' => '"%'.$searchTerm.'%"'));

 while ($row = $prep->fetch(PDO::FETCH_ASSOC)) 
  $i++;
  $result[$i]['subText'] = $row['hs_pk'];
  $result[$i]['subText'] = $row['hs_text'];
  $result[$i]['subDid'] = $row['hs_did'];
  $result[$i]['devDid'] = $row['hd_did'];
  $result[$i]['devText'] = $row['hd_text'];
  $result[$i]['vendorText'] = $row['hv_text'];
  $result[$i]['classText'] = $row['hc_text'];
 
    $dbh = null;
   
catch (PDOException $e) 
  print "Error!: " . $e->getMessage() . "<br/>";
  die();

我也尝试了以下方法(SQL WHERE 子句和 prep->执行行都发生了变化):

WHERE hs.hs_text LIKE CONCAT(\'%\', ?, \'%\') 
$ret = $prep->execute(array($searchTerm));

WHERE hs.hs_text LIKE "%:searchTerm%" 
$ret = $prep->execute(array(':searchTerm' => $searchTerm));

WHERE hs.hs_text LIKE ":searchTerm" 
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));

等等……

【问题讨论】:

这可能只是一个转置问题,但你没有附上你的 sql 语句 - 你需要在它的末尾加上一个撇号 (')。 这是一个换位问题。如果我忘记了 ' 我相信 PHP 会完全吓坏的,哈哈。不过,感谢您非常快速的回复。 var_dump() $dbh、$prep 和 $ret 会得到什么?它们是您期望的值吗?您是否尝试过使用 mysql_* 系列函数运行相同的查询进行比较? 这里是每个(以及脚本的输出)的 var 转储:doSearch,搜索词:com connected to DB object(PDO)#32 (0) object(PDOStatement) #33 (1) ["queryString"]=> string(586) "SELECT ...语句太大,但与脚本中的 $sql 变量匹配... bool(false) ret: Array ( ) 结果:应该添加行我没有尝试过 mysql_* 系列函数。我需要查找文档,因为我不熟悉这些。 【参考方案1】:
$ret = $prep->execute(array(':searchTerm' => '"%'.$searchTerm.'%"'));

这是错误的。你不需要双引号。

WHERE hs.hs_text LIKE ":searchTerm" 
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));

这也是错误的。 尝试:

$prep = $dbh->prepare($sql);
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));

说明:准备好的语句不只是简单地进行字符串替换。它们传输数据与查询完全分开。只有在将值嵌入查询时才需要引号。

【讨论】:

感谢您的解释。可能解决不了这个问题,但我会记在内存中以备日后使用。 @Tlm 你还是应该接受他的回答。它直接回答了您的问题。接受它不需要任何费用。【参考方案2】:
$prep = $dbh->prepare($sql);
$ret = $prep->execute(array('searchTerm' => $searchTerm));

【讨论】:

这个分析器不完整(你指的是哪个 $sql?),缺少一些信息(如何进行“.. LIKE '%FOO%'”搜索?)并且缺少任何信息解释。像这样放置的一些代码不是答案,IMO,只是一个断章取义的事情。【参考方案3】:

好吧,我解决了这个问题。坦率地说,我是个白痴……感谢大家看到这一点并提供良好的反馈。问题是表名中的拼写错误(我更改了,所以这里没有人能够看到我的问题开始......)。不过,这些建议确实让我找到了问题所在,所以谢谢亚当、jkndrkn 和 troelskn。

作为记录,以下组合效果很好:

WHERE aw_hcl_subdevices.hs_text LIKE CONCAT(\'%\', ?, \'%\')
$ret = $prep->execute(array($searchTerm));

【讨论】:

-1 这不是正确的方法。您应该将 CONCAT() 用于三个 static 字符串文字,因为它会为您打开特定类型的 SQL 注入(我忘记了名称)。 不知道是谁对上述评论投了赞成票,但奇怪的是——他们都没有说出注射的名字。可能是因为这种“注入”根本不存在。 如果@TheodoreR.Smith 还在 SO 附近,他很想听听他的意见。 More specifically on this distinct question 如果你用谷歌搜索“静态字符串 sql 注入”,这是第一个结果。 @Mike,你的意思是这样的问题,由上面的评论产生? This?这看起来像The Bible said that all words in The Bible are true.

以上是关于PHP PDO 准备语句——MySQL LIKE 查询的主要内容,如果未能解决你的问题,请参考以下文章

pdo 使用通配符准备语句

使用 PHP PDO 准备语句和 MySQL 选择字段为空的行

使用 PDO 准备语句从搜索字段中使用多个关键字进行 LIKE 查询

使用 PDO 准备好的语句 MySQL 错误

在 PHP 中到处使用准备好的语句? (PDO)

PDO、Mysql 和原生预处理语句