You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP、MySQL、HTML流程中&符号导致的数据库查询失效问题

问题:PHP/HTML/MySQL中&符号导致搜索失效

在PHP+HTML+MySQL的业务流程里,遇到了一个&符号引发的问题:当输入框输入“H&C”时,数据库检索不到对应记录,但输入“US”却能正常返回结果。


数据库创建语句

DROP DATABASE IF EXISTS testamp;
CREATE DATABASE testamp;
USE testamp;

DROP TABLE IF EXISTS acronym;
CREATE TABLE acronym(
    id               INT           NOT NULL  AUTO_INCREMENT  PRIMARY KEY,
    terminology      VARCHAR(255)  NOT NULL  UNIQUE,
    acronym          VARCHAR(255)  NOT NULL,
    index (terminology),
    index (acronym)
);

INSERT INTO acronym
(terminology, acronym)
values
 ( "United States", "US"  )
,( "Humanitarian and compassionate", "H&C"  )
;

可通过select * from acronym where acronym like 'h%c';验证数据库中存在“H&C”记录。


前端输入框代码

<input type="text" name="acronym" size="50" 
  placeholder="Enter an acronym" 
  autofocus
  onkeydown="if (event.keyCode == 13) { this.form.submit(); return false; }"
>

PHP处理逻辑

输入 sanitize 函数

function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}

通过POST获取输入时调用:$acronym = test_input($_POST["acronym"]);

数据库查询代码

$link = create_link() or die("create_link");
$stmt = $link->prepare(
    'SELECT acronym, terminology FROM acronym WHERE acronym like ? ORDER BY acronym'
);
$like_value="%$acronym%";
$stmt->bind_param("s", $like_value) or die("bind_param");
$stmt->execute() or die("execute");
$stmt->store_result();
echo "<p>num_rows: " .$stmt->num_rows .PHP_EOL;

问题原因

问题出在htmlspecialchars()函数上:这个函数的作用是把HTML特殊字符转义成实体,比如会把&转换成&amp;。当你输入“H&C”时,经过这个函数处理后,$acronym的值变成了H&amp;C,用这个值去数据库匹配,自然找不到原本存储的“H&C”记录。而“US”没有特殊字符,所以不受影响。

解决方案

htmlspecialchars()是用于将内容输出到HTML页面时防止XSS攻击的,不是用于数据库查询的输入处理。你需要调整处理逻辑:

  1. 修改test_input函数,去掉htmlspecialchars():
function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  // 移除htmlspecialchars,数据库查询不需要HTML转义
  return $data;
}
  1. 如果你需要在页面上输出查询到的内容,在输出的时候再使用htmlspecialchars()处理,比如:
// 假设从数据库取出的字段是$row['acronym']
echo htmlspecialchars($row['acronym']);

另外,你使用预处理语句(prepare+bind_param)的做法是正确的,这已经足够防止SQL注入,不需要额外的HTML转义来处理数据库查询的输入。

内容的提问来源于stack exchange,提问作者sofname

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:40:19