php怎么实现搜索高亮_php关键词匹配并加亮显示【检索】

1次阅读

preg_replace是最稳妥的关键词高亮方式,需转义关键词、加i修饰符、用$0替换、中文需归一化空白、先htmlspecialchars再高亮、多词按长度降序处理。

php怎么实现搜索高亮_php关键词匹配并加亮显示【检索】

preg_replace 是最稳妥的关键词高亮方式

直接用 str_replace 看似简单,但大小写不敏感、无法处理“php”和“phpstorm”重叠匹配、还可能把 HTML 标签里的内容也误替换(比如把 <span></span> 里的 “pan” 高亮)。preg_replace 能真正按“词”匹配,可控性强。

  • 必须用 preg_quote($keyword, '/') 转义用户输入,否则关键词含 .+[ 就会崩正则
  • i 修饰符实现不区分大小写,模式写成 '/'.preg_quote($kw, '/').'/'.'i'
  • 替换内容用 '<mark>$0</mark>'$0 表示完整匹配项,比 $1 更安全(不用捕获组)
  • 如需只匹配独立单词(避免 “stack” 匹配到 “stacking”),加上词边界 b'/b'.preg_quote($kw, '/').'b/i'

中文搜索前必须统一空格和转义

用户可能输全角空格、半角空格、甚至换行符,直接拿去匹配大概率失败。PHP 不像 jss 自动覆盖所有空白,得手动归一化。

  • 先用 str_replace([' ', "r", "n"], ' ', $keyword) 把全角空格、回车、换行换成普通空格
  • preg_replace('/s+/', ' ', $keyword) 合并多个连续空格
  • 如果关键词是多个词(如 “人工智能 开源”),拆成数组后逐个高亮,不要拼成一个正则——容易因顺序或边界冲突漏匹配
  • 注意:中文词无天然 b 边界,b 对汉字无效;若需“整词”效果,得靠前后字符判断(如用 (? 和 <code>(?!w)),但多数场景直接去掉 b 更实际

必须先 htmlspecialchars 再高亮,否则 xss

用户搜 <script>alert(1)</script>,如果你先替换再转义,<mark></mark> 标签会被当作文本输出,而脚本仍保留在 <p>用户搜 <code><script>alert(1)</script>,如果你先替换再转义,<mark></mark> 标签会被当作文本输出,而脚本仍保留在 $0 里执行——高亮功能直接变成 XSS 入口。

里执行——高亮功能直接变成 XSS 入口。

  • 正确顺序:先 htmlspecialchars($text, ENT_QUOTES, 'UTF-8'),再对结果做 preg_replace
  • 别用 htmlentities,它会把中文也转成实体,影响可读性
  • 如果原文已含 HTML(比如富文本内容),不能直接 htmlspecialchars 全文——会把原有标签也转义。此时应先用 DOMDocument 或专用库剥离/保留标签逻辑,再对纯文本部分高亮

多关键词高亮要排序,长词优先

搜 “php” 和 “phpstorm”,如果先替 “php”,后面 “phpstorm” 就变成 “phpstorm”,再替 “phpstorm” 就找不到原串了——高亮被污染。

立即学习PHP免费学习笔记(深入)”;

  • 把关键词数组按长度降序排列:usort($keywords, function($a, $b) { return strlen($b) - strlen($a); });
  • 循环每个词调用 preg_replace,而不是用 | 拼成单个正则(后者无法保证优先级,且 $0 只能取第一个匹配)
  • 如果关键词来自用户输入(如 GET 参数),记得 trim()array_filter() 去掉空值,防止生成 //i 这种非法正则

高亮看着只是加个 <mark></mark>,但关键词来源、HTML 上下文、中文边界、多词顺序这四点没理清,轻则显示错乱,重则执行任意脚本。真正在生产环境用,别省那几行排序和转义。

text=ZqhQzanResources