- Laravel を使用すると、AJAX を使用したシンプルな検索エンジンから、Laravel Scout や Algolia、Meilisearch、Elasticsearch などの外部検索エンジンを使用した高度な全文検索まで、あらゆるものを実装できます。
- 軽量な検索の場合、フロントエンドで Alpine.js またはネイティブ フェッチ リクエストを使用してフィルタリングすると、サーバーの過負荷が回避され、小さなリストでのユーザー エクスペリエンスが向上します。
- Laravel Scout は、さまざまな検索エンジンとの統合を一元化し、モデルを検索可能としてマークしたり、インデックスを管理したり、クエリを均一に起動したりすることを容易にします。
- エンジン (SaaS、オープンソース、またはデータベース) の選択は、データの量、検索の複雑さ、プロジェクトのパフォーマンスとメンテナンスの要件に基づいて行う必要があります。
Laravelを使い始めて、 即座に応答するリアルタイム検索エンジンAJAX と fetch、jQuery、Alpine.js、Scout と Algolia または Meilisearch、フロントエンド フィルタリングなど、数千通りのアプローチがあり、迷ってしまうのは簡単です。幸いなことに、Laravel エコシステムは、試行錯誤で失敗することなく、スムーズで高速な検索をセットアップするために必要なものを実質的にすべてすでに提供しています。
この記事では組み立て方を説明します Laravelのさまざまな種類のリアルタイム検索古典的なAJAXオートコンプリートから、Laravel Scoutを使った全文検索、Algolia、Meilisearch、データベース自体、さらにはElasticsearchといった検索エンジンまで、幅広い選択肢があります。また、データ量が少ない場合にブラウザ内で直接データをフィルタリングできる、Alpine.jsを使った軽量な代替手段もご紹介します。
Laravel のリアルタイム検索とは何ですか? 基本的な仕組みはどのように機能しますか?
リアルタイム検索の背後にある考え方は、 ユーザーがテキストフィールドに入力するとクエリがトリガーされ、ページをリロードすることなく結果が更新されます。技術的には、これには3つの主要コンポーネント、つまりLaravelバックエンド、ブラウザのJavaScript、そしてJSON形式でのデータ交換が関係します。
一方では、 Laravelはサーバー層として機能します リクエストの受信、検索パラメータ(入力されたテキスト)の解釈、データベースへのクエリ、そして通常はJSON形式の構造化されたレスポンスの返送を担います。このレスポンスは、成功、エラー、または結果が見つからなかったことを示すことができます。
もう一方の端に、 JavaScript はユーザー イベントをリッスンする役割を担います。 検索入力欄では、バックエンドに非同期リクエスト(AJAX)を送信し、ブラウザがページ全体を更新することなく、返されたデータをページに表示します。これは、ネイティブフェッチ、jQuery AJAX、またはAlpine.jsのような小規模なリアクティブライブラリを使用して実現できます。
この基本的なメカニズムを使えば、 いくつかのレコードによるシンプルなオートコンプリート関連性、ページ区切り、フィルターを備えた高度な全文検索エンジンまで、Laravel Scout などのライブラリや検索に最適化された外部検索エンジンによってサポートされています。
基本的なリアルタイム検索エンジンのモデル、ルート、コントローラー
JavaScript を詳しく調べる前に、Laravel 側が適切に構成されていることを確認する必要があります。 検索用のEloquentモデル、明確なルート、専用のコントローラー 検索ロジックをリアルタイムで管理します。
最初のステップは、検索対象となるテーブルを表すEloquentモデルを用意することです。国別のテーブルと、次のようなモデルを想像してみてください。 カントリー 非常にシンプルで、タイムスタンプがなく、一括割り当てが可能です。
検索用の最小限の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']);
ルートルートは welcome ビューを返しますが、URL /search は検索機能のために予約されていますコントローラーの index() メソッドはフォームと検索入力を表示し、search() メソッドはブラウザーから送信された非同期リクエストを処理します。
コントローラーでは、非常に実用的なパターンを実装できます。 エラーが発生した場合に備えてデフォルトのレスポンス配列を準備する 実際に有効な AJAX リクエストであり、クエリが問題なく実行される場合にのみ上書きします。
コントローラーには 同様の構造 この:
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形式で送信されるため、フロントエンドの作業が大幅に簡素化されます。
リアクティブ検索のためのブレードビューと JavaScript フェッチ
モデル、ルート、コントローラーの準備ができたら、表示される部分を構築します。 検索フィールドと結果を表示するブロックを備えたフォーム、さらにバックグラウンドでリクエストを行う JavaScript も含まれます。
ブレードビューは非常にシンプルです。 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>
この例ではスクリプト 検索入力のキーアップイベントをリッスンするキー入力ごとに/searchパスへのフェッチリクエストがトリガーされます。フィールドの現在のテキストはJSON形式で送信され、AJAXであることを示すX-Requested-Withなどの主要なヘッダーと、Laravelのネイティブ保護を回避するためのCSRFトークンが含まれます。
応答が到着すると、JSON に変換され、動的に生成されます。 結果を含む小さなHTMLリストあるいは、クエリがデータを返さなかった場合に「結果が見つかりません」といったメッセージを表示するなど、ページの再読み込みを必要とせず、ユーザーにとって自然な形でこれらを実現します。
このパターンは、UXの細部を少し変更することでさらに洗練させることができます。 遅延(デバウンス) キーストロークの間にローダーを表示したり、ネットワーク エラーを処理して、何かが失敗したときにインターフェイスがフリーズしたように見えるのを防ぎます。
jQueryを使用したLaravelとAJAXによるライブ検索
フェッチは最近かなり普及してきましたが、 jQuery AJAXは依然として非常に人気がある レガシープロジェクトや、既に実装済みのチームでも同様です。考え方は全く同じです。ユーザーの入力内容をキャプチャし、非同期リクエストを送信して、DOMを更新します。
ライブ検索のための Laravel での jQuery を使用した一般的なワークフローには、通常、次の基本的な手順が含まれます。 特定のルートを定義し、専用のコントローラーを作成し、検索入力を使用してブレードビューを構築します。 最後に、入力時に AJAX をトリガーする jQuery コードを追加します。
プロセスは次のように機能します。ユーザーが入力を開始すると、 jQueryはサーバーにクエリを送信します 検索文字列を入力します。Laravel はデータベース内の情報をフィルタリングし、一致した結果を JSON 形式で返します。そして jQuery は一致結果を反映するようにページ上の HTML コンテナを更新します。これらはすべて数ミリ秒で実行されます。
jQueryを使用する利点は これはAJAXの構文をほぼ要約したものです プロジェクトに既にライブラリがある場合は、非常に簡単に読み取ることができます。ただし、最新のJavaScriptとネイティブフェッチを使用できる場合は、不要な依存関係が追加される可能性があります。
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;
},
}
ビューでは、各カードまたはデータ行に属性が付けられます すでに小文字で用意されているテキストを含むデータ検索テキストしたがって、フィルターは 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プロジェクトを作成するか、既存のプロジェクトを再利用します起動するには、Docker(例えばLaravel Sailなど)を使用し、Composerでライブラリをインストールします。インストールが完了したら、scout.php設定ファイルを公開し、使用するドライバーに応じて環境変数を調整します。
典型的なワークフローは、ComposerでScoutをインストールし、その設定を公開し、 SCOUT_QUEUE=true でインデックスキューをアクティブ化します .env ファイルでは、リソースを大量に消費する操作がバックグラウンドで処理されるようにすることで、アプリケーションの応答時間を改善します。さらに、DB_HOST が使用しているデータベースを指していることを確認する必要があります。これは、Docker コンテナを使用している場合に特に重要です。
モデルがスカウトサーチに参加するには、 Searchable特性を追加して明示的に検索可能とマークするにはたとえば、タイトル フィールドを持つ列車のテーブルを表す Train モデルがある場合、次のように定義できます。
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 with Algolia: 超高速SaaS検索
Algoliaは、 大量のデータに対して非常に高速かつ関連性の高い検索を提供するインデックス、関連性ルール、同義語などを管理するための Web パネルがあり、Scout と公式 PHP クライアントを通じて Laravel と非常にうまく統合されます。
ScoutでAlgoliaを使用するには、ComposerでPHPクライアントをインストールし、.envファイルに資格情報(アプリケーションIDと管理者APIキー)を登録し、 SCOUT_DRIVER=algolia を設定する Scoutにこのエンジンを使用するように指示します。Algoliaパネルから、アプリケーションIDと管理キーの両方を取得できます。
環境が設定されると、次のような方法を使用できます。 Train::search('text')->ページネーション(6) コントローラに直接組み込んでインデックス付きフィールドで検索を実行し、結果をページ区切りの Eloquent 形式で受け取り、Blade ビューに渡すことができます。
例えばコントローラーがあれば index すべての列車をリストするか、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();
}
対応するビューでは、 新しい列車を登録するためのフォーム そして、送信時に検索をトリガーする titlesearch フィールドを持つ別の GET フォームを作成します。その後は、列車のコレクションを反復処理し、Laravel によって生成されるページネーションリンクを利用して、各フィールドをテーブルに表示するだけです。
Meilisearch、データベース、コレクションを備えたScout
外部サービスを避けたい場合は、 Meilisearchはオープンソースの検索エンジンです ローカルまたは自社インフラ上にデプロイできます。ScoutはAlgoliaとほぼ同様の方法でMeilisearchと統合できます。ドライバーを変更し、MEILISEARCH_HOSTとMEILISEARCH_KEY変数を.envファイルに追加するだけです。
これを使用するには、Meilisearch PHPクライアントをインストールし、 SCOUT_DRIVER=メイリサーチ MEILISEARCH_HOST をインスタンスの URL(例:http://127.0.0.1:7700)に設定します。既にレコードがある場合は、コマンド php artisan scout:import "App\Models\Train" でインデックスを作成し、エンジンで利用できるようにします。
小規模または中規模のアプリケーションでは、 スカウトドライバーデータベースこれは、MySQLまたはPostgreSQLデータベースの全文インデックスとLIKEコマンドを活用します。この場合、外部サービスは必要ありません。SCOUT_DRIVER=database を設定するだけで、Scoutはデータベース自体を検索エンジンとして使用します。
もうXNUMXつの興味深いオプションは メモリ内のEloquentコレクションで動作するドライバーコレクションこのエンジンは、WHERE句とコレクションフィルタリングを使用して結果をフィルタリングし、Laravelがサポートするあらゆるデータベースと互換性があります。`SCOUT_DRIVER=collection` を指定するか、Scoutの設定ファイルを調整してより具体的な設定を行うこともできます。
Explorerを使用したElasticsearchとの統合
検索ニーズが 膨大な量のデータとリアルタイム分析を扱うElasticsearchは定番のツールです。Laravelエコシステムでは、ScoutとElasticsearchを統合する最新の方法として、モデルとElasticsearchクラスター間のブリッジとして機能するExplorerコントローラーを使用するのが一般的です。
これを実現するために、通常は Docker が使用され、典型的なサービス (Laravel、MySQL、Redis、Meilisearch など) に加えて、豊富な docker-compose ファイルも使用されます。 Elasticsearch と Kibana コンテナ次に、Composer 経由で jeroen-g/explorer パッケージをインストールし、その構成ファイルを公開して、どのモデルをインデックス化するかを指定します。
config/explorer.phpファイルでは、indexesキーの下にモデルを登録することができます。例えば、 App\Models\Train::クラスさらに、すべてが Elasticsearch を指すように、.env ファイルで SCOUT_DRIVER=elastic を使用して Scout ドライバーを elastic に変更します。
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 エコシステムを離れることなく、
フェッチやjQueryを使った基本的なオートコンプリートから、Alpine.jsを使ったフロントエンドフィルタリング、Laravel Scoutと様々なドライバーを使った全文検索まで、これらのアプローチをすべて活用することで、 Laravelはリアルタイム検索を実装するための幅広いオプションを提供します プロジェクトの規模、必要なパフォーマンス、維持するインフラストラクチャに合わせてカスタマイズできます。
目次
- Laravel のリアルタイム検索とは何ですか? 基本的な仕組みはどのように機能しますか?
- 基本的なリアルタイム検索エンジンのモデル、ルート、コントローラー
- リアクティブ検索のためのブレードビューと JavaScript フェッチ
- jQueryを使用したLaravelとAJAXによるライブ検索
- Alpine.js を使用したフロントエンドでのリアルタイム フィルタリングと検索
- Laravel Scout: 専用エンジンによる全文検索
- Laravel Scout with Algolia: 超高速SaaS検索
- Meilisearch、データベース、コレクションを備えたScout
- Explorerを使用したElasticsearchとの統合