Laravel 即時搜尋完整指南

最後更新: 5月2025
  • Laravel 讓您可以實現從使用 AJAX 的簡單搜尋引擎到使用 Laravel Scout 和 Algolia、Meilisearch 或 Elasticsearch 等外部搜尋引擎的高級全文搜尋等各種功能。
  • 對於輕量級搜索,使用 Alpine.js 或原生 fetch 請求在前端進行過濾可以避免伺服器過載,並改善小型列表的使用者體驗。
  • Laravel Scout 集中集成了與不同搜尋引擎的集成,使模型更容易被標記為可搜尋、管理索引以及統一啟動查詢。
  • 引擎(SaaS、開源或資料庫)的選擇應基於資料量、搜尋的複雜性以及專案的效能和維護要求。

Laravel 中的即時搜尋

當你開始使用 Laravel 並且需要… 即時搜尋引擎,反應迅速面對上千種可能的解決方案,很容易迷失方向:使用 fetch 的 AJAX、jQuery、Alpine.js、使用 Algolia 或 Meil​​search 的 Scout、前端過濾等等。好消息是,Laravel 生態系統已經提供了幾乎所有你需要的東西,可以讓你輕鬆建立一個流暢快速的搜尋系統。

本文將介紹如何組裝 Laravel 中不同類型的即時搜索從經典的 AJAX 自動補全到使用 Laravel Scout 和 Algolia、Meilisearch 等搜尋引擎進行全文搜索,甚至直接使用資料庫或 Elasticsearch,應有盡有。此外,當資料量較小時,您也可以使用 Alpine.js 等輕量級方案直接在瀏覽器中進行資料過濾。

Laravel 中的即時搜尋是什麼?它的基本運作原理是什麼?

即時搜尋背後的理念是: 當使用者在文字欄位中輸入內容時觸發查詢後,無需重新載入頁面即可更新結果。從技術角度來看,這涉及三個關鍵元件:Laravel 後端、瀏覽器 JavaScript 以及 JSON 格式的資料交換。

一方面, Laravel 充當伺服器層。 它負責接收請求、解析搜尋參數(輸入的文字)、查詢資料庫,並傳回結構化的回應,通常以 JSON 格式傳回。該回應可以指示成功、錯誤或未找到結果。

在另一端, JavaScript 負責監聽使用者事件。 在搜尋框中,向後端發送非同步請求(AJAX),並在不刷新瀏覽器的情況下將傳回的資料顯示在頁面上。這可以透過原生 Fetch、jQuery AJAX 或像 Alpine.js 這樣的小型響應式函式庫來實現。

有了這個基本機制,你可以從…開始構建 簡單的自動完成功能,包含少量記錄,直至高級全文搜尋引擎,具備相關性、分頁和過濾器功能,並由 Laravel Scout 等庫和針對搜尋優化的外部搜尋引擎提供支援。

基本即時搜尋引擎的模型、路由和控制器

在深入學習 JavaScript 之前,你需要確保 Laravel 部分結構清晰、組織良好: 一個用於搜尋的 Eloquent 模型、清晰的路徑和一個專用控制器 即時管理搜尋邏輯。

第一步是建立一個 Eloquent 模型來表示你要搜尋的表格。假設有一個國家/地區列表的表格,以及一個名為 `countries` 的模型。 父母 非常簡單,不帶時間戳,並且允許批量分配:

一個用於搜尋的最小 Eloquent 模型範例:

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Pais extends Model
{
use HasFactory;
protected $guarded = [];
public $timestamps = false;
}

這裡指出的是模型 Pais 位於標準的 Laravel 命名空間中。它繼承自 Model 類,允許你透過空數組的方式,使用 create() 方法為任何欄位賦值。透過設定 public $timestamps = false 來停用時間戳,可以避免因表中缺少 created_at 和 updated_at 欄位而導致的問題。

下一步是定義 負責處理搜尋引擎顯示和 AJAX 請求的路由一個非常常見的方案是將用於顯示視圖的 GET 路由和用於接收即時查詢的 POST 路由結合起來:

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BuscadorController;

Route::get('/', function () {
return view('welcome');
});

Route::get('buscador', [BuscadorController::class, 'index']);
Route::post('buscador', [BuscadorController::class, 'buscar']);

根路由返回歡迎頁面,而 URL /search 保留用於搜尋功能控制器的 index() 方法顯示表單和搜尋輸入框,而 search() 方法處理從瀏覽器發送的非同步請求。

在控制器中,您可以實現非常實用的模式: 準備一個預設的回應數組以應對錯誤。 只有當請求確實有效且查詢執行無誤時,才會覆寫它。

控制器可能具有 類似結構 這個:

namespace App\Http\Controllers;

use App\Models\Pais;
use Illuminate\Http\Request;

class BuscadorController extends Controller
{
public function index()
{
return view('welcome');
}

public function buscar(Request $request)
{
$response = [
'success' => false,
'message' => 'Hubo un error',
];

if ($request->ajax()) {
$data = Pais::where('nombre', 'like', $request->texto.'%')
->take(10)
->get();

$response = [
'success' => true,
'message' => 'Consulta correcta',
'data' => $data,
];
}

return response()->json($response);
}
}

此時你已經擁有 完整的後端週期:接收 AJAX 請求、檢查請求類型(是否為 AJAX)、使用 WHERE LIKE 子句進行查詢並限制結果 使用 `take(10)` 將請求數量控制在合理範圍內,以避免資料庫過載。回應始終以 JSON 格式發送,這大大簡化了前端的工作。

Blade 視圖和 JavaScript fetch 用於響應式搜尋

模型、路徑和控制器準備就緒後,就可以開始建置可見部分了: 包含搜尋欄位和用於顯示結果的模組的表單以及負責在後台發出請求的 JavaScript 程式碼。

Blade視圖可以非常簡單,依賴 CSRF 令牌 Laravel 會注入該函數來驗證 POST 請求,而該函數也位於一個方便使用的搜尋輸入框中:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<strong><meta name="csrf-token" content="{{ csrf_token() }}"></strong>
<title>Laravel</title>
</head>
<body>

<form action="" method="post">
<input type="search" name="texto" id="buscar">
</form>

<div id="resultado"></div>

<script>
window.addEventListener('load', function () {
const buscar = document.getElementById('buscar');
const resultado = document.getElementById('resultado');

buscar.addEventListener('keyup', function () {
fetch('/buscador', {
method: 'post',
body: JSON.stringify({ texto: buscar.value }),
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': document.head.querySelector('[name~="csrf-token"][content]').content,
},
})
.then(response => response.json())
.then(data => {
let html = '';
if (data.success) {
html += '<ul>';
for (let i in data.data) {
html += '<li>' + data.data[i].nombre + '</li>';
}
html += '<ul>';
} else {
html += 'No existen resultados';
}
resultado.innerHTML = html;
});
});
});
</script>

</body>
</html>

在這個例子中,腳本 監聽搜尋輸入框的 keyup 事件每次按鍵都會觸發向 /search 路徑發送獲取請求。欄位的目前文字以 JSON 格式發送,並包含 X-Requested-With 等關鍵標頭,以表明這是 AJAX 請求,同時還包含 CSRF 令牌以繞過 Laravel 的原生保護機制。

當回應到達時,它會轉換為 JSON 格式並動態產生。 一個包含結果的小型 HTML 列表或者,當查詢未傳回任何資料時,顯示類似「未找到結果」的訊息。所有這些操作都無需重新加載頁面,對用戶來說非常自然。

這種模式可以透過添加一些小的使用者體驗細節來進一步完善,例如添加一個 延遲(防手震) 按鍵之間顯示載入指示器或處理網路錯誤,以防止出現故障時介面出現凍結現象。

使用 Laravel 和 AJAX 以及 jQuery 進行即時搜索

雖然現在fetch已經獲得了很大的發展, jQuery AJAX 仍然非常流行 在遺留專案或已實現此功能的團隊中,想法完全相同:擷取使用者輸入的內容,發出非同步請求,然後刷新 DOM。

在 Laravel 中使用 jQuery 進行即時搜尋的典型工作流程通常包括以下基本步驟: 定義特定路由,建立專用控制器,建立具有搜尋輸入的 Blade 視圖 最後,加入 jQuery 程式碼,以便在輸入時觸發 AJAX。

這個過程是這樣的:當使用者開始輸入時, jQuery 向伺服器發送查詢 使用搜尋字串,Laravel 會過濾資料庫中的信息,傳回包含符合結果的 JSON,然後 jQuery 會更新頁面上的 HTML 容器以反映符合結果,所有這些都只需幾毫秒即可完成。

使用 jQuery 的優點在於: 它基本上概括了 AJAX 的語法。 如果你已經在專案中安裝了該庫,那麼閱讀起來就非常簡單。但是,如果你可以使用現代 JavaScript 和原生 fetch,那麼你新增的額外依賴項可能就沒必要了。

使用 Alpine.js 在前端實現即時過濾和搜尋

當要顯示的資料量相對較小時(例如, 少於 50 件),但並非總是值得搭建一個具有複雜搜尋功能的後端。在這種情況下,一個非常方便的選擇是 使用 Alpine.js 直接在瀏覽器中進行篩選無需在使用者輸入時向伺服器發出請求。

其想法是預先計算每個元素的搜尋字串(例如,名稱、描述和類別,全部小寫),將其儲存在 data-search-text 屬性中,然後讓 Alpine.js 處理其餘部分。 根據文字內容顯示或隱藏元素 在搜尋欄中。

Alpine.js 元件可以有類似這樣的結構: 篩選項

{
search: '',
hasResults: true,
selectedValue: '',
init() {
this.$watch('search', () => this.filterItems());
this.$nextTick(() => this.$refs.searchInput?.focus());
},
filterItems() {
const searchLower = this.search.toLowerCase().trim();
const cards = this.$el.querySelectorAll('.item-card');
let visibleCount = 0;

cards.forEach(card => {
const text = card.dataset.searchText || '';
const isVisible = searchLower === '' || text.includes(searchLower);
card.style.display = isVisible ? '' : 'none';
if (isVisible) visibleCount++;
});

this.hasResults = visibleCount > 0;
},
}

在視圖中,每張卡片或每行資料都會攜帶一個屬性。 data-search-text 文字已預先準備好,格式為小寫因此,過濾過程簡化為 JavaScript 中的 includes() 函數,對於短列表來說速度非常快:

<input type="search" x-model="search" x-ref="searchInput" placeholder="Buscar..." />
<div>
<div class="item-card" data-search-text="formulario contacto simple">
<h3>Formulario de contacto</h3>
<p>Formulario de contacto simple</p>
</div>
</div>

此外,您可以僅在以下情況下顯示空狀態區塊: 目前搜尋詞沒有結果。邀請使用者修改文字或透過按鈕清除字段,該按鈕會將搜尋重置為空字串。

這種方法有明顯的優點: 搜尋過程中沒有伺服器調用。互動幾乎是瞬時的,邏輯高度本地化,易於調試。它非常適合用於快速選擇器、專案選擇模態框或嵌入 Laravel 頁面中的小型目錄。

Laravel Scout:使用專用引擎進行全文搜索

當事情變得嚴重,你需要 快速、相關且可擴展的全文搜索在 Laravel 中,Laravel Scout 是自然而然的選擇。 Scout 是一個整合層,它允許你透過外部控制器輕鬆地將 Eloquent 模型與 Algolia、Meilisearch 等搜尋引擎、你自己的資料庫、記憶體集合,甚至是 Elasticsearch 連接起來。

要開始使用 Scout,通常的做法是: 建立一個新的 Laravel 專案或重複使用一個現有的 Laravel 專案要啟動它,請使用 Docker(例如,配合 Laravel Sail),然後使用 Composer 安裝程式庫。安裝完成後,發布 scout.php 設定文件,並根據您要使用的驅動程式調整環境變數。

典型的工作流程是使用 Composer 安裝 Scout,發布其配置, 使用 SCOUT_QUEUE=true 啟動索引隊列 在 .env 檔案中,確保資源密集型操作在背景處理,從而提升應用程式的回應速度。此外,必須確保 DB_HOST 指向您正在使用的資料庫,如果您使用的是 Docker 容器,這一點尤其重要。

模特兒若想參加 Scout 的選拔活動,必須符合以下條件: 若要將其明確標記為可搜索,請新增 Searchable 特性。例如,如果您有一個 Train 模型,它表示一個包含 title 欄位的火車表,您可以這樣定義它:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Train extends Model
{
use Searchable;

protected $fillable = ['title'];

public function searchableAs()
{
return 'trains_index';
}
}

searchableAs 方法允許 自訂搜尋引擎中的索引名稱Scout 不會使用從模型派生的預設名稱,而是會接管控制權。接下來,Scout 會根據所選驅動程序,處理與遠端或本機索引的建立、更新和刪除操作的同步。

Laravel Scout 與 Algolia:閃電般快速的 SaaS 搜索

Algolia 是一家專注於 SaaS 服務的公司。 提供對大量數據進行快速且相關的搜索它有一個用於管理索引、相關性規則、同義詞等的 Web 面板,並且透過 Scout 和官方 PHP 用戶端與 Laravel 整合得非常好。

要將 Algolia 與 Scout 結合使用,您需要使用 Composer 安裝其 PHP 用戶端,並在 .env 檔案中註冊您的憑證(應用程式 ID 和管理員 API 金鑰)。 設定 SCOUT_DRIVER=algolia 指示 Scout 使用此引擎。您可以從 Algolia 控制面板取得應用程式 ID 和管理金鑰。

環境配置完成後,您可以使用以下方法: Train::search('text')->paginate(6) 直接在控制器中對索引欄位執行搜索,以分頁 Eloquent 格式接收結果,準備將其傳遞給 Blade 視圖。

例如你可以擁有一個控制器 指數 列出所有列車,或如果收到 titlesearch 參數則執行搜索,以及一個用於將新列車插入索引的 create 方法:

public function index(Request $request)
{
if ($request->has('titlesearch')) {
$trains = Train::search($request->titlesearch)->paginate(6);
} else {
$trains = Train::paginate(6);
}

return view('Train-search', compact('trains'));
}

public function create(Request $request)
{
$this->validate($request, ['title' => 'required']);
Train::create($request->all());
return back();
}

在相應的視圖中,您可以組合 新列車登記表 還有一個包含標題搜尋欄位的 GET 表單,提交後即可觸發搜尋。然後,您只需遍歷列車集合,並利用 Laravel 生成的分頁鏈接,將它們的字段顯示在表格中即可。

利用 Meil​​search、資料庫和館藏進行偵察

如果您不想使用外部服務, Meilisearch 是一個開源搜尋引擎。 您可以將其部署在本地或您的基礎架構上。 Scout 與 Meil​​search 的整合方式與 Algolia 非常相似,只需更改驅動程式並將 MEILISEARCH_HOST 和 MEILISEARCH_KEY 變數添加到 .env 檔案即可。

要使用它,您需要安裝 Meil​​​​isearch PHP 客戶端並進行調整 SCOUT_DRIVER=meilisearch 並將 MEILISEARCH_HOST 指向實例 URL(例如,http://127.0.0.1:7700)。如果您之前已有記錄,可以使用指令 `php artisan scout:import "App\Models\Train"` 對其進行索引,以便引擎可以存取這些記錄。

在規模較小或中等的應用場景中,您也可以選擇 偵察兵駕駛員資料庫這會利用 MySQL 或 PostgreSQL 資料庫上的全文索引和 LIKE 指令。在這種情況下,您不需要外部服務;只需將 SCOUT_DRIVER 設定為 database,Scout 即可使用資料庫本身作為其搜尋引擎。

另一個有趣的選擇是 驅動程式集合,它處理記憶體中的 Eloquent 集合。該引擎使用 WHERE 子句和集合過濾來篩選結果,並且相容於 Laravel 支援的任何資料庫。您可以使用 `SCOUT_DRIVER=collection` 來啟動它,或透過調整 Scout 設定檔來進行更具體的設定。

使用 Explorer 與 Elasticsearch 集成

如果您的搜尋需求涉及 處理海量數據和即時分析Elasticsearch 是一個經典的資料庫管理工具。在 Laravel 生態系統中,將其與 Scout 整合的一種現代方法是使用 Explorer 控制器,它充當模型和 Elasticsearch 集群之間的橋樑。

為此,通常會使用 Docker,以及一個內容豐富的 docker-compose 文件,該文件除了包含典型的服務(Laravel、MySQL、Redis、Meilisearch 等)之外, Elasticsearch 和 Kibana 容器然後透過 Composer 安裝 jeroen-g/explorer 套件,並發布其設定檔以指示應該索引哪些模型。

在 config/explorer.php 檔案中,您可以透過新增以下程式碼在 indexes 鍵下註冊您的模型: App\Models\Train::class此外,您需要在 .env 檔案中將 Scout 驅動程式變更為 elastic,將 SCOUT_DRIVER=elastic 設為 Elastic,以便所有內容都指向 Elasticsearch。

在 Train 模型中,必須實作 Explored 介面並重寫該方法。 可映射它定義了要傳送到索引的欄位對應。一個簡單的範例是:

use JeroenG\Explorer\Application\Explored;
use Laravel\Scout\Searchable;

class Train extends Model implements Explored
{
use Searchable;

protected $fillable = ['title'];

public function mappableAs(): array
{
return [
'id' => $this->id,
'title' => $this->title,
];
}
}

從現在開始, 您可以使用相同的 Scout 介面在 Elasticsearch 上發起搜尋。受益於極低的回應時間和該引擎的全部查詢能力,但又無需離開 Laravel 生態系統。

所有這些方法——從使用 fetch 或 jQuery 的基本自動完成功能,到使用 Alpine.js 的前端過濾,再到使用 Laravel Scout 和各種驅動程式的全文搜尋—— Laravel 為您提供了豐富的選項來實現即時搜尋。 根據您的專案規模、所需性能以及您願意維護的基礎設施量身定制。

  電玩遊戲程式設計:如何入門 - 逐步指南