本文目录导读:

在PHP项目中实现模糊搜索,常见的方法有以下几种:
使用SQL LIKE 语句(最基础)
MySQL示例
<?php
$search = $_GET['search'] ?? '';
$keyword = "%{$search}%";
// 使用预处理语句防止SQL注入
$stmt = $pdo->prepare("SELECT * FROM products
WHERE name LIKE :keyword
OR description LIKE :keyword2");
$stmt->execute([
':keyword' => $keyword,
':keyword2' => $keyword
]);
$results = $stmt->fetchAll();
?>
MySQL全文搜索(性能更好)
先创建全文索引
ALTER TABLE products ADD FULLTEXT INDEX ft_index (name, description);
PHP代码
<?php
$search = $_GET['search'] ?? '';
// 自然语言模式
$stmt = $pdo->prepare("SELECT *,
MATCH(name, description) AGAINST(:keyword) AS relevance
FROM products
WHERE MATCH(name, description) AGAINST(:keyword IN NATURAL LANGUAGE MODE)
ORDER BY relevance DESC");
$stmt->execute([':keyword' => $search]);
$results = $stmt->fetchAll();
?>
使用搜索引擎(高级方案)
Elasticsearch示例
<?php
require 'vendor/autoload.php';
use Elasticsearch\ClientBuilder;
$client = ClientBuilder::create()->build();
$params = [
'index' => 'products',
'body' => [
'query' => [
'multi_match' => [
'query' => $_GET['search'],
'fields' => ['name^3', 'description'] // name字段权重更高
]
]
]
];
$response = $client->search($params);
$results = $response['hits']['hits'];
?>
完整示例:前后端分离的模糊搜索
后端 (search.php)
<?php
header('Content-Type: application/json');
try {
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$search = $_GET['q'] ?? '';
if (empty($search)) {
echo json_encode(['status' => 'error', 'message' => '请输入搜索关键词']);
exit;
}
// 防止SQL注入
$keyword = '%' . $search . '%';
$stmt = $pdo->prepare("SELECT id, name, description, price
FROM products
WHERE name LIKE :keyword
OR description LIKE :keyword
LIMIT 20");
$stmt->execute([':keyword' => $keyword]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'status' => 'success',
'data' => $results,
'total' => count($results)
]);
} catch (PDOException $e) {
echo json_encode(['status' => 'error', 'message' => '数据库错误']);
}
?>
前端 (search.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">模糊搜索示例</title>
<style>
#searchResults { margin-top: 20px; }
.result-item { padding: 10px; border-bottom: 1px solid #eee; }
</style>
</head>
<body>
<input type="text" id="searchInput" placeholder="输入搜索关键词...">
<div id="searchResults"></div>
<script>
const searchInput = document.getElementById('searchInput');
const resultsDiv = document.getElementById('searchResults');
let timeoutId;
searchInput.addEventListener('input', function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => performSearch(this.value), 300);
});
function performSearch(query) {
if (query.length < 2) {
resultsDiv.innerHTML = '';
return;
}
fetch(`search.php?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
displayResults(data.data);
} else {
resultsDiv.innerHTML = `<p>${data.message}</p>`;
}
})
.catch(error => {
resultsDiv.innerHTML = '<p>搜索出错,请重试</p>';
});
}
function displayResults(results) {
if (results.length === 0) {
resultsDiv.innerHTML = '<p>未找到相关结果</p>';
return;
}
let html = '';
results.forEach(item => {
html += `
<div class="result-item">
<h3>${highlightText(item.name)}</h3>
<p>${highlightText(item.description)}</p>
<p>价格: ¥${item.price}</p>
</div>
`;
});
resultsDiv.innerHTML = html;
}
// 高亮搜索关键词
function highlightText(text) {
const keyword = searchInput.value;
if (!keyword) return text;
const regex = new RegExp(`(${keyword})`, 'gi');
return text.replace(regex, '<mark>$1</mark>');
}
</script>
</body>
</html>
性能优化建议
数据库层面
-- 添加索引优化LIKE查询 CREATE INDEX idx_name ON products(name); -- 对于前缀模糊搜索有效 -- 避免以%开头的LIKE查询 -- 使用全文索引 ALTER TABLE products ADD FULLTEXT INDEX ft_search (name, description);
PHP层面
// 1. 限制搜索长度
$search = substr($search, 0, 50);
// 2. 清理特殊字符
$search = preg_replace('/[^\p{L}\p{N}\s]/u', '', $search);
// 3. 缓存搜索结果
$cacheKey = 'search_' . md5($search);
$cached = apcu_fetch($cacheKey);
if ($cached !== false) {
return $cached;
}
// ... 执行查询
apcu_store($cacheKey, $results, 300); // 缓存5分钟
选择建议
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| LIKE | 小数据量(<1万条) | 简单易用 | 性能差,不支持中文分词 |
| 全文索引 | 中等数据量 | 性能较好,支持中文 | 配置复杂 |
| Elasticsearch | 大数据量,复杂搜索 | 功能强大,支持分词 | 需要额外服务 |
| Sphinx | 全文搜索需求 | 性能优异 | 配置维护复杂 |
选择哪种方案取决于你的数据量、搜索复杂度和性能要求,对于大多数中小型项目,MySQL全文搜索已经足够。