本文目录导读:

我来用一个简单的搜索引擎案例展示PHP对全文检索的支持,这个案例使用MySQL的全文索引功能。
数据库准备
-- 创建数据库和表
CREATE DATABASE IF NOT EXISTS search_engine;
USE search_engine;
-- 创建文章表,使用MyISAM引擎支持全文索引
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FULLTEXT INDEX ft_index (title, content)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
-- 插入示例数据
INSERT INTO articles (title, content) VALUES
('PHP入门教程', 'PHP是一种流行的服务器端脚本语言,特别适合Web开发'),
('MySQL数据库基础', 'MySQL是最流行的关系型数据库管理系统之一'),
('全文检索技术', '全文检索可以快速在大文本中找到匹配的内容'),
('PHP高级编程', '深入学习PHP面向对象编程和设计模式'),
('数据库优化技巧', '合理使用索引可以大幅提升查询性能');
PHP搜索实现
<?php
// database.php - 数据库连接配置
class Database {
private static $instance = null;
private $connection;
private function __construct() {
$this->connection = new mysqli(
'localhost',
'root',
'',
'search_engine'
);
if ($this->connection->connect_error) {
die("连接失败: " . $this->connection->connect_error);
}
$this->connection->set_charset("utf8mb4");
}
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Database();
}
return self::$instance;
}
public function getConnection() {
return $this->connection;
}
}
<?php
// search.php - 搜索引擎核心类
class SearchEngine {
private $db;
public function __construct() {
$this->db = Database::getInstance()->getConnection();
}
/**
* 执行全文搜索
* @param string $query 搜索关键词
* @param int $limit 返回结果数量
* @return array 搜索结果
*/
public function search($query, $limit = 10) {
$results = [
'success' => true,
'total' => 0,
'data' => [],
'time' => 0
];
try {
$start_time = microtime(true);
// 清理和验证输入
$query = $this->sanitizeInput($query);
if (empty($query)) {
throw new Exception("搜索关键词不能为空");
}
// 预处理查询
$prepared_query = $this->prepareSearchQuery($query);
// 执行全文检索
$sql = "SELECT
id,
title,
content,
MATCH(title, content) AGAINST(? IN BOOLEAN MODE) as relevance
FROM articles
WHERE MATCH(title, content) AGAINST(? IN BOOLEAN MODE)
ORDER BY relevance DESC
LIMIT ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("ssi", $prepared_query, $prepared_query, $limit);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// 高亮显示搜索关键词
$row['title'] = $this->highlightKeywords($row['title'], $query);
$row['content'] = $this->highlightKeywords(
$this->truncateText($row['content'], 200),
$query
);
$results['data'][] = $row;
}
$results['total'] = count($results['data']);
$results['time'] = microtime(true) - $start_time;
$stmt->close();
} catch (Exception $e) {
$results['success'] = false;
$results['error'] = $e->getMessage();
}
return $results;
}
/**
* 预处理搜索查询
*/
private function prepareSearchQuery($query) {
// 分词处理
$words = preg_split('/[\s,,、.。;;]+/', $query);
$prepared = [];
foreach ($words as $word) {
$word = trim($word);
if (!empty($word)) {
// 使用布尔模式操作符增强搜索
$prepared[] = "+" . $word . "*";
}
}
return implode(" ", $prepared);
}
/**
* 高亮显示关键词
*/
private function highlightKeywords($text, $keywords) {
$keywords = preg_split('/[\s,,、.。;;]+/', $keywords);
foreach ($keywords as $keyword) {
$keyword = trim($keyword);
if (!empty($keyword)) {
$text = preg_replace(
"/(" . preg_quote($keyword, "/") . ")/iu",
"<mark>$1</mark>",
$text
);
}
}
return $text;
}
/**
* 截取文本
*/
private function truncateText($text, $length = 200) {
if (mb_strlen($text) > $length) {
return mb_substr($text, 0, $length) . "...";
}
return $text;
}
/**
* 清理输入
*/
private function sanitizeInput($input) {
$input = trim($input);
$input = stripslashes($input);
$input = htmlspecialchars($input);
return $input;
}
}
<?php
// index.php - 搜索界面
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">简易搜索引擎</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
.search-form {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.search-form input[type="text"] {
flex: 1;
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 16px;
}
.search-form input[type="submit"] {
padding: 12px 30px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
.search-form input[type="submit"]:hover {
background-color: #0056b3;
}
.result-stats {
color: #666;
margin: 20px 0;
padding: 10px;
background: #f8f9fa;
border-radius: 5px;
}
.search-result {
padding: 15px;
border: 1px solid #eee;
margin-bottom: 15px;
border-radius: 5px;
}
.search-result:hover {
background: #f8f9fa;
}
.result-title {
font-size: 18px;
color: #1a0dab;
margin-bottom: 10px;
}
.result-content {
color: #545454;
line-height: 1.6;
}
.result-relevance {
color: #999;
font-size: 12px;
margin-top: 10px;
}
mark {
background-color: #ffeb3b;
padding: 2px 4px;
}
.no-result {
text-align: center;
color: #999;
padding: 40px;
}
.error {
color: #dc3545;
text-align: center;
padding: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>🔍 简易搜索引擎</h1>
<form method="GET" action="" class="search-form">
<input type="text"
name="q"
placeholder="输入搜索关键词..."
value="<?php echo isset($_GET['q']) ? htmlspecialchars($_GET['q']) : ''; ?>"
required>
<input type="submit" value="搜索">
</form>
<?php
if (isset($_GET['q']) && !empty($_GET['q'])) {
require_once 'database.php';
require_once 'search.php';
$searchEngine = new SearchEngine();
$results = $searchEngine->search($_GET['q']);
if ($results['success']) {
?>
<div class="result-stats">
找到约 <?php echo $results['total']; ?> 条结果 (用时 <?php echo number_format($results['time'], 4); ?> 秒)
</div>
<?php if (count($results['data']) > 0): ?>
<?php foreach ($results['data'] as $item): ?>
<div class="search-result">
<div class="result-title">
<?php echo $item['title']; ?>
</div>
<div class="result-content">
<?php echo $item['content']; ?>
</div>
<div class="result-relevance">
相关度: <?php echo number_format($item['relevance'], 2); ?>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="no-result">
<p>未找到与 "<?php echo htmlspecialchars($_GET['q']); ?>" 相关的结果</p>
<p>建议:尝试使用不同的关键词</p>
</div>
<?php endif; ?>
<?php } else { ?>
<div class="error">
<p>搜索出错:<?php echo $results['error']; ?></p>
</div>
<?php }
} else { ?>
<div class="no-result">
<p>请输入搜索关键词开始搜索</p>
</div>
<?php } ?>
</div>
</body>
</html>
使用说明
- 数据库配置:修改
database.php中的数据库连接信息 - 运行环境:需要 PHP 和 MySQL 环境
- 访问方式:通过浏览器访问
index.php
特性说明
- 全文索引:使用 MySQL 的 FULLTEXT 索引加速搜索
- 布尔模式:支持 +word* 模式进行精确匹配
- 结果高亮:高亮显示搜索关键词
- 相关度排序:按匹配度降序排列
- 性能统计:显示搜索用时和结果数量
这个案例展示了PHP如何利用MySQL的全文索引实现高效的搜索功能,适合中小型网站的内容搜索需求。