核心邏輯
- 取得使用者輸入關鍵字 (GET/POST)。
- SQL
LIKE 查詢符合資料。
- 用
preg_replace() 將關鍵字包裝 HTML 標籤 (如 <mark> 或 <span class="highlight">)。
完整範例
<?php
// 資料庫連線 (PDO)
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '');
$keyword = $_GET['keyword'] ?? '';
$highlighted = [];
if ($keyword !== '') {
// 多關鍵字支援:以空格分割
$keywords = array_filter(array_map('trim', explode(' ', $keyword)));
$placeholders = implode(' OR ', array_fill(0, count($keywords), 'title LIKE ? OR content LIKE ?'));
$params = [];
foreach ($keywords as $kw) {
$like = "%$kw%";
$params[] = $like;
$params[] = $like;
}
$sql = "SELECT id, title, content FROM articles WHERE $placeholders";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 高亮處理
foreach ($rows as &$row) {
foreach ($keywords as $kw) {
// 使用 preg_quote 避免關鍵字含特殊正則字元
$pattern = '/' . preg_quote($kw, '/') . '/iu';
$replacement = '<mark>$0</mark>';
$row['title'] = preg_replace($pattern, $replacement, $row['title']);
$row['content'] = preg_replace($pattern, $replacement, $row['content']);
}
$highlighted[] = $row;
}
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8">
<style>mark { background: #ff0; padding: 0 2px; border-radius: 2px; }</style></head>
<body>
<form method="get">
<input type="text" name="keyword" value="= htmlspecialchars($keyword) ?>" placeholder="輸入關鍵字,空格分隔">
<button type="submit">搜尋</button>
</form>
<?php foreach ($highlighted as $row): ?>
<article style="border-bottom:1px solid #eee; padding:10px 0;">
<h3>= $row['title'] ?></h3>
<div>= $row['content'] ?></div>
</article>
<?php endforeach; ?>
</body></html>
關鍵函數說明
preg_quote($kw, '/'):將關鍵字中的正則元字元 (如 . * ? ( ) [ ] 等) 轉義,防止正則錯誤或注入。
/iu 修飾符:i 不區分大小寫,u 正確處理 UTF-8 多位元組字元。
$0:替換字串中代表完整匹配到的子字串。
效能優化建議
- 大量資料改用全文搜尋引擎 (MySQL FULLTEXT、Elasticsearch、Meilisearch)。
- 前端高亮:傳回原始資料 + 關鍵字清單,由 JavaScript (如
mark.js) 在瀏覽器端高亮,減少伺服器 CPU 負載。
- 快取熱門搜尋結果 (Redis)。