你能否用一个简单的搜索引擎案例展示PHP对全文检索的支持

wen PHP项目 44

本文目录导读:

你能否用一个简单的搜索引擎案例展示PHP对全文检索的支持

  1. 数据库准备
  2. PHP搜索实现
  3. 使用说明
  4. 特性说明

我来用一个简单的搜索引擎案例展示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>

使用说明

  1. 数据库配置:修改 database.php 中的数据库连接信息
  2. 运行环境:需要 PHP 和 MySQL 环境
  3. 访问方式:通过浏览器访问 index.php

特性说明

  • 全文索引:使用 MySQL 的 FULLTEXT 索引加速搜索
  • 布尔模式:支持 +word* 模式进行精确匹配
  • 结果高亮:高亮显示搜索关键词
  • 相关度排序:按匹配度降序排列
  • 性能统计:显示搜索用时和结果数量

这个案例展示了PHP如何利用MySQL的全文索引实现高效的搜索功能,适合中小型网站的内容搜索需求。

抱歉,评论功能暂时关闭!