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

如何通过PHP优化搜索功能,实现部分匹配、大小写不敏感及拼写容错查询

如何通过PHP优化搜索功能,实现部分匹配、大小写不敏感及拼写容错查询

我完全懂你的痛点——现在这个搜索太"死板"了:必须整个字符串匹配、大小写错一点或者拼漏一个字母就查无结果,这和用户日常用的搜索体验差太远了。下面我就用PHP+PDO一步步优化你的代码,解决这些问题,完全贴合你的需求。

一、先搞定核心需求:大小写不敏感+分词模糊匹配

你当前的代码是把整个搜索词当成一个整体做模糊匹配,比如搜"book 1: conquest",只会找包含这个完整短语的记录,而用户实际想要的是只要包含"book"、"1"、"conquest"任意一个(或者全部)关键词的结果,同时大小写不影响。

修改后的基础优化代码

<?php
define("DB_HOST", "localhost");
define("DB_NAME", "officiallasereyeswebsite");
define("DB_CHARSET", "utf8");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// 1. 预处理搜索词:清理、拆分单个关键词
$search = isset($_GET['search']) ? trim($_GET['search']) : '';
// 去掉多余空格,拆分关键词,过滤空值
$keywords = array_filter(preg_split('/\s+/', $search));

$pdo = new PDO(
    "mysql:host=".DB_HOST.";charset=".DB_CHARSET.";dbname=".DB_NAME,
    DB_USER, DB_PASSWORD,
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]
);

$results = [];
if (!empty($keywords)) {
    // 2. 动态构建SQL条件:每个关键词对应一个模糊匹配规则
    $conditions = [];
    $params = [];
    foreach ($keywords as $keyword) {
        // 统一转小写,彻底解决大小写敏感问题
        $lowerKeyword = strtolower($keyword);
        // 对item和code字段分别做模糊匹配
        $conditions[] = "(LOWER(`item`) LIKE ? OR LOWER(`code`) LIKE ?)";
        $params[] = "%{$lowerKeyword}%";
        $params[] = "%{$lowerKeyword}%";
    }

    // 用AND连接=必须包含所有关键词;用OR连接=包含任意关键词,按需选
    $sql = "SELECT * FROM `items` WHERE " . implode(' AND ', $conditions);
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    $results = $stmt->fetchAll();
}

// 返回AJAX结果
if (isset($_GET["ajax"])) {
    echo json_encode($results);
}
?>

这段代码的关键改进点

  1. 分词处理:把搜索词拆成单个关键词,比如"book 1: conquest"会拆成["book", "1:", "conquest"],每个关键词单独匹配数据库字段
  2. 大小写完全不敏感:用LOWER()把数据库字段和搜索词都转成小写,不管你的数据库 collation 是啥,都能保证大小写不影响结果
  3. 灵活的匹配规则:可以自由切换AND/OR——用AND就是必须包含所有关键词,用OR就是包含任意关键词就显示,完全贴合你的业务需求

二、实现拼写容错:PHP端用编辑距离过滤结果

如果用户拼错单词(比如把"conquest"写成"conqest"),我们可以用PHP自带的levenshtein()函数计算两个字符串的"编辑距离"(也就是需要增、删、改几个字符才能让两个字符串一样),保留差异小的结果。

带拼写容错的完整代码

<?php
define("DB_HOST", "localhost");
define("DB_NAME", "officiallasereyeswebsite");
define("DB_CHARSET", "utf8");
define("DB_USER", "root");
define("DB_PASSWORD", "");

$search = isset($_GET['search']) ? trim($_GET['search']) : '';
// 预处理:去掉标点,拆分关键词
$cleanSearch = preg_replace('/[^\w\s]/u', '', $search);
$keywords = array_filter(preg_split('/\s+/', $cleanSearch));

$pdo = new PDO(
    "mysql:host=".DB_HOST.";charset=".DB_CHARSET.";dbname=".DB_NAME,
    DB_USER, DB_PASSWORD,
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]
);

$rawResults = [];
if (!empty($keywords)) {
    // 先拿候选结果:放宽SQL匹配条件,比如匹配关键词的前缀,避免漏过相似结果
    $conditions = [];
    $params = [];
    foreach ($keywords as $keyword) {
        $lowerKeyword = strtolower($keyword);
        // 取关键词的前n-1个字符做匹配,比如"conqest"就匹配包含"conqe"的记录
        $shortKeyword = substr($lowerKeyword, 0, max(2, strlen($lowerKeyword)-1));
        $conditions[] = "(LOWER(`item`) LIKE ? OR LOWER(`code`) LIKE ?)";
        $params[] = "%{$shortKeyword}%";
        $params[] = "%{$shortKeyword}%";
    }
    // 用OR连接,拿到所有可能的候选结果
    $sql = "SELECT * FROM `items` WHERE " . implode(' OR ', $conditions);
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    $rawResults = $stmt->fetchAll();
}

// 2. PHP端用编辑距离过滤,保留拼写相似的结果
$results = [];
$maxEditDistance = 2; // 允许的最大差异:2意味着最多2个字符的错误,按需调整
foreach ($rawResults as $item) {
    $isMatch = false;
    // 合并item和code字段,统一做匹配
    $itemContent = strtolower($item['item'] . ' ' . $item['code']);
    
    foreach ($keywords as $keyword) {
        $lowerKeyword = strtolower($keyword);
        $minDistance = PHP_INT_MAX;
        
        // 遍历内容的子串,找到和关键词最相似的部分
        $keywordLen = strlen($lowerKeyword);
        for ($i = 0; $i <= strlen($itemContent) - $keywordLen; $i++) {
            $subStr = substr($itemContent, $i, $keywordLen);
            $distance = levenshtein($lowerKeyword, $subStr);
            if ($distance < $minDistance) {
                $minDistance = $distance;
            }
        }
        
        // 如果编辑距离在阈值内,就认为匹配成功
        if ($minDistance <= $maxEditDistance) {
            $isMatch = true;
            break;
        }
    }
    
    if ($isMatch) {
        $results[] = $item;
    }
}

// 返回AJAX结果
if (isset($_GET["ajax"])) {
    echo json_encode($results);
}
?>

拼写容错的逻辑说明

  1. 先拿候选结果:通过SQL匹配关键词的前缀(比如去掉最后一个字符),先把所有可能的相似结果捞出来,避免PHP端处理全表数据
  2. 编辑距离过滤:用levenshtein()计算关键词和结果内容的差异度,只保留差异在2个字符以内的结果(这个阈值你可以自己调,越大容错越高)
  3. 额外预处理:加了去掉标点的逻辑,比如把"1:"变成"1",让搜索更智能

三、额外优化小技巧

  • 智能清理搜索词:可以用preg_replace('/[^\w\s]/u', '', $search)去掉所有非文字和空格的字符,让关键词更干净
  • 性能优化:如果你的数据量很大,PHP端的编辑距离过滤会有点慢,可以先让MySQL用全文索引(MATCH AGAINST)缩小范围,再在PHP端做二次过滤
  • 结果排序:可以根据编辑距离给结果排序,把最相似的结果放在最前面

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:58:02