- 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 і як працюють основи?
Ідея пошуку в режимі реального часу полягає в тому, коли користувач вводить текст у текстове полеЗапит запускається, і результати оновлюються без перезавантаження сторінки. Технічно це включає три ключові компоненти: бекенд Laravel, JavaScript браузера та обмін даними у форматі JSON.
З одного боку, Laravel виступає в ролі серверного рівня Він відповідає за отримання запитів, інтерпретацію параметрів пошуку (введеного тексту), запити до бази даних та повернення структурованої відповіді, зазвичай у форматі JSON. Ця відповідь може свідчити про успіх, помилку або про те, що результати не знайдено.
На іншому кінці, JavaScript відповідає за прослуховування подій користувача. У полі пошуку надсилайте асинхронні запити (AJAX) до серверної частини та відображайте повернуті дані на сторінці без повного оновлення браузером. Це можна зробити за допомогою нативного fetch, jQuery AJAX або невеликих реактивних бібліотек, таких як Alpine.js.
За допомогою цього базового механізму ви можете будувати з Просте автозаповнення з кількома записами, аж до розширеної повнотекстової пошукової системи з релевантністю, пагінацією та фільтрами, що підтримується бібліотеками, такими як Laravel Scout, та зовнішніми пошуковими системами, оптимізованими для пошуку.
Модель, маршрути та контролер для базової пошукової системи реального часу
Перш ніж заглиблюватися в JavaScript, вам потрібно переконатися, що частина Laravel добре організована: красномовна модель для пошуку, чіткі маршрути та спеціалізований контролер керувати логікою пошуку в режимі реального часу.
Перший крок – створити модель 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']);
Кореневий маршрут повертає вітальне представлення, тоді як 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" та обмеження результатів. до розумного числа за допомогою 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-список із результатамиабо повідомлення на кшталт «Результатів не знайдено», коли запит не повертає даних. І все це без перезавантаження сторінки, природним для користувача способом.
Цей шаблон можна додатково вдосконалити за допомогою невеликих UX-деталей, таких як додавання затримка (усунення дребезгу) між натисканнями клавіш, відображати завантажувач або обробляти мережеві помилки, щоб запобігти зависанню інтерфейсу у разі виникнення збою.
Пошук у реальному часі за допомогою Laravel та AJAX з використанням jQuery
Хоча сьогодні апорт набув значної популярності, jQuery AJAX залишається дуже популярним у застарілих проектах або в командах, де це вже впроваджено. Ідея абсолютно та сама: фіксувати те, що вводить користувач, робити асинхронний запит та оновлювати DOM.
Типовий робочий процес з jQuery в Laravel для пошуку в реальному часі зазвичай включає такі основні кроки: визначити певний маршрут, створити спеціалізований контролер, побудувати вигляд Blade з пошуковим запитом І нарешті, додайте jQuery-код, який запускає AJAX під час введення.
Процес працює так: коли користувач починає друкувати, jQuery надсилає запит на сервер за допомогою рядка пошуку. Laravel фільтрує інформацію в базі даних, повертає JSON з результатами пошуку, а jQuery оновлює HTML-контейнер на сторінці, щоб відобразити збіги, і все це за лічені мілісекунди.
Перевага використання jQuery полягає в тому, що Це досить точно підсумовує синтаксис AJAX І це дуже просто прочитати, якщо у вашому проєкті вже є бібліотека. Однак ви додаєте додаткову залежність, яка може бути не потрібною, якщо ви можете працювати із сучасним JavaScript та нативним fetch.
Фільтрація та пошук у режимі реального часу на фронтенді за допомогою Alpine.js
Коли дані, що відображаються, відносно невеликі (наприклад, менше ніж 50 XNUMX товарів), не завжди варто налаштовувати серверну частину зі складними пошуками. У таких випадках дуже зручним варіантом є Фільтруйте безпосередньо у браузері за допомогою 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;
},
}
У поданні кожна картка або рядок даних матиме атрибут текст-пошуку-даних з уже підготовленим текстом у нижньому регістріТаким чином, фільтр зводиться до функції includes() у JavaScript, яка дуже швидко працює для коротких списків:
<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 та налаштуйте змінні середовища відповідно до драйвера, який ви хочете використовувати.
Типовий робочий процес полягав би в тому, щоб встановити Scout за допомогою Composer, опублікувати його конфігурацію та активувати чергу індексації за допомогою 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 з Algolia: блискавично швидкий SaaS-пошук
Algolia — це SaaS-сервіс, орієнтований на пропонувати дуже швидкий та релевантний пошук у великих обсягах данихВін має веб-панель для керування індексами, правилами релевантності, синонімами тощо, а також дуже добре інтегрується з Laravel через Scout та офіційний PHP-клієнт.
Щоб використовувати Algolia зі Scout, вам потрібно буде встановити його PHP-клієнт за допомогою Composer, зареєструвати свої облікові дані у файлі .env (ідентифікатор програми та ключ API адміністратора) та встановити SCOUT_DRIVER=алголія щоб повідомити Scout про необхідність використання цього механізму. З панелі Algolia ви можете отримати як ідентифікатор програми, так і адміністративний ключ.
Після налаштування середовища можна використовувати такі методи, як 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-форму з полем titlesearch, яке запускає пошук після відправлення. Потім вам просто потрібно пройтися по колекції потягів та відобразити їхні поля в таблиці, використовуючи посилання на сторінки, згенеровані Laravel.
Розвідник з Meilisearch, базою даних та колекціями
Якщо ви бажаєте уникнути зовнішніх послуг, Meilisearch — це пошукова система з відкритим кодом який ви можете розгорнути локально або на вашій інфраструктурі. Scout інтегрується з Meilisearch дуже схожим чином на Algolia, просто змінюючи драйвер та додаючи змінні MEILISEARCH_HOST та MEILISEARCH_KEY до файлу .env.
Щоб ним скористатися, потрібно встановити PHP-клієнт Meilisearch, налаштувати SCOUT_DRIVER=meilisearch та вкажіть MEILISEARCH_HOST на URL-адресу екземпляра (наприклад, http://127.0.0.1:7700). Якщо у вас вже були попередні записи, ви можете проіндексувати їх за допомогою команди php artisan scout:import "App\Models\Train", щоб рушій мав їх доступними.
У менших або помірних застосуваннях ви також можете вибрати База даних водіїв-скаутівЦе використовує повнотекстові індекси та команди LIKE у вашій базі даних MySQL або PostgreSQL. У цьому випадку вам не потрібен зовнішній сервіс; просто встановіть SCOUT_DRIVER=database, щоб Scout використовував саму базу даних як пошукову систему.
Інший цікавий варіант - колекція драйверів, яка працює з колекціями Eloquent у пам'ятіЦей рушій фільтрує результати за допомогою речень WHERE та фільтрації колекцій і сумісний з будь-якою базою даних, що підтримується Laravel. Ви можете активувати його за допомогою `SCOUT_DRIVER=collection` або налаштувавши файл конфігурації Scout для більш конкретних налаштувань.
Інтеграція з Elasticsearch за допомогою Explorer
Якщо ваші потреби в пошуку включають робота з величезними обсягами даних та аналіз у режимі реального часуElasticsearch — це класика. В екосистемі Laravel сучасним способом його інтеграції зі Scout є використання контролера Explorer, який діє як місток між вашими моделями та кластером Elasticsearch.
Для цього зазвичай використовується Docker разом із повноцінним файлом docker-compose, який, окрім типових сервісів (Laravel, MySQL, Redis, Meilisearch тощо), Контейнери Elasticsearch та KibanaПотім ви встановлюєте пакет jeroen-g/explorer через Composer та публікуєте його файл конфігурації, щоб вказати, які моделі слід індексувати.
У файлі config/explorer.php ви можете зареєструвати свої моделі під ключем indexes, наприклад, додавши App\Models\Train::classКрім того, ви змінюєте драйвер Scout на elastic у файлі .env за допомогою SCOUT_DRIVER=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,
];
}
}
Відтепер, Ви можете запускати пошук на Elasticsearch, використовуючи той самий інтерфейс Scout., користуючись перевагами дуже низького часу відгуку та повної потужності запитів цього рушія, але не виходячи за межі екосистеми Laravel.
З усіма цими підходами — від базового автозаповнення за допомогою fetch або jQuery до фільтрації на фронтенді за допомогою Alpine.js та повнотекстового пошуку за допомогою Laravel Scout та різних драйверів — Laravel надає вам величезний спектр можливостей для реалізації пошуку в режимі реального часу. адаптовано до розміру вашого проєкту, необхідної вам продуктивності та інфраструктури, яку ви готові підтримувати.
Зміст
- Що таке пошук у реальному часі в Laravel і як працюють основи?
- Модель, маршрути та контролер для базової пошукової системи реального часу
- Перегляд Blade та JavaScript fetch для реактивного пошуку
- Пошук у реальному часі за допомогою Laravel та AJAX з використанням jQuery
- Фільтрація та пошук у режимі реального часу на фронтенді за допомогою Alpine.js
- Laravel Scout: Повнотекстовий пошук за допомогою спеціалізованих рушіїв
- Laravel Scout з Algolia: блискавично швидкий SaaS-пошук
- Розвідник з Meilisearch, базою даних та колекціями
- Інтеграція з Elasticsearch за допомогою Explorer