本文目录导读:

实现PHP搜索功能通常涉及前端表单提交、后端接收处理、数据库查询以及结果展示四个环节,根据数据的复杂度和搜索需求,常见的有以下几种实现方案:
基础模糊搜索(LIKE查询)
适用于小型项目或简单字段(如文章标题、用户名)。
前端表单示例:
<form method="GET" action="search.php">
<input type="text" name="keyword" placeholder="输入关键词" value="<?php echo htmlspecialchars($_GET['keyword'] ?? ''); ?>">
<button type="submit">搜索</button>
</form>
后端搜索逻辑(search.php):
<?php
// 连接数据库(使用PDO,防止SQL注入)
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 获取并过滤输入
$keyword = $_GET['keyword'] ?? '';
$keyword = trim($keyword);
if (!empty($keyword)) {
// 使用LIKE进行模糊匹配,并处理特殊字符
$searchTerm = '%' . $keyword . '%';
// 准备预处理语句,防止SQL注入
$stmt = $pdo->prepare("SELECT id, title, content, created_at FROM articles WHERE title LIKE :keyword OR content LIKE :keyword2 ORDER BY created_at DESC");
$stmt->execute([':keyword' => $searchTerm, ':keyword2' => $searchTerm]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
$results = []; // 或无关键词时显示所有数据
}
?>
结果展示:
<?php if (!empty($results)): ?>
<ul>
<?php foreach ($results as $article): ?>
<li>
<a href="article.php?id=<?= $article['id'] ?>"><?= htmlspecialchars($article['title']) ?></a>
<small><?= $article['created_at'] ?></small>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>未找到相关内容。</p>
<?php endif; ?>
缺点: LIKE %keyword% 无法利用索引,数据量大时性能差。
全文检索(MySQL内置全文索引)
适用于对中文文本或长文本(如文章内容、博客)进行快速搜索,MySQL 5.6+ 及以上版本支持中文全文索引(需要ngram插件)。
步骤:
-
创建全文索引(以InnoDB表为例):
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title, content) WITH PARSER ngram;
-
使用MATCH AGAINST查询:
$keyword = trim($_GET['keyword']); if (!empty($keyword)) { $stmt = $pdo->prepare("SELECT id, title, content, created_at, MATCH(title, content) AGAINST(:keyword IN BOOLEAN MODE) AS relevance FROM articles WHERE MATCH(title, content) AGAINST(:keyword2 IN BOOLEAN MODE) ORDER BY relevance DESC"); $stmt->execute([':keyword' => $keyword, ':keyword2' => $keyword]); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); }
注意: 中文搜索需要配置ngram分词器,且MySQL默认配置对中文支持有限,较复杂场景建议使用Elasticsearch。
使用Elasticsearch(推荐,适合中大型项目)
ES是一个分布式全文搜索引擎,功能强大,支持中文分词、高亮显示、模糊匹配、权重排序等。
简要集成流程:
- 安装Elasticsearch及PHP客户端包(
elasticsearch/elasticsearchvia Composer)。 - 建立索引:定义文档映射(mapping),设置IK分词器(中文)。
- 写入数据:从MySQL同步数据到ES(可用Logstash或手动同步)。
- 搜索查询:
$client = ClientBuilder::create()->setHosts(['localhost:9200'])->build(); $params = [ 'index' => 'articles', 'body' => [ 'query' => [ 'multi_match' => [ 'query' => $keyword, 'fields' => ['title^3', 'content'] // title权重更高 ] ], 'highlight' => [ 'fields' => ['title' => new \stdClass(), 'content' => new \stdClass()] ] ] ]; $response = $client->search($params);
优势: 性能好、支持拼音纠错、聚合分析、毫秒级响应。
使用专业的PHP搜索引擎库(轻量级替代)
- Meilisearch:类Rust编写,安装简单,开箱即用,支持中文分词,有PHP客户端。
- Algolia:SaaS服务(付费),但API简单,适合快速集成。
- Sphinx Search:老牌开源搜索引擎,PHP有成熟扩展,适合大文本检索。
关键安全与性能建议
- 防止SQL注入:永远使用预处理语句(PDO或mysqli),不要拼接SQL。
- 输入过滤:使用
htmlspecialchars()输出到前端,避免XSS。 - 限制长度和频率:过滤空搜索,限制关键词长度(如
mb_strlen控制),防止恶意大负载。 - 分页:使用
LIMIT和OFFSET分页(或用LIMIT + 游标优化)。 - 高亮:对结果关键字进行高亮(使用
str_replace或正则preg_replace包裹<mark>或<span>)。
如何选择?
| 方案 | 适合场景 | 是否支持中文分词 | 性能 | 实施复杂度 |
|---|---|---|---|---|
| LIKE模糊 | 小型、字段少 | 不支持(汉字按单字匹配) | 差 | 低 |
| MySQL全文检索 | 中型、文本为主 | 有限(ngram) | 一般 | 低~中 |
| Elasticsearch | 中大型、高并发 | 优秀(IK分词器) | 优 | 高 |
| Meilisearch | 中小型、快速搭建 | 内置支持 | 好 | 中 |
简单推荐:
- 数据量小(<1万条) → LIKE 够用,但注意分页。
- 数据量中等(几万~几十万) → MySQL全文索引 或 Meilisearch。
- 数据量大、搜索要求高 → Elasticsearch。
希望这些方案能帮到你!如果有具体的场景(如中文分词、实时更新、搜索建议等),可以进一步细化问题。