- Laravel ju lejon të zbatoni gjithçka, nga motorë kërkimi të thjeshtë me AJAX deri te kërkime të avancuara me tekst të plotë duke përdorur Laravel Scout dhe motorë kërkimi të jashtëm si Algolia, Meilisearch ose Elasticsearch.
- Për kërkime të lehta, filtrimi në frontend me Alpine.js ose me kërkesa native për marrjen e të dhënave shmang mbingarkesën e serverit dhe përmirëson përvojën e përdoruesit në lista të vogla.
- Laravel Scout centralizon integrimin me motorë të ndryshëm kërkimi dhe e bën të lehtë shënimin e modeleve si të kërkueshme, menaxhimin e indekseve dhe nisjen e pyetjeve në mënyrë uniforme.
- Zgjedhja e motorit (SaaS, me burim të hapur ose bazë të dhënash) duhet të bazohet në vëllimin e të dhënave, kompleksitetin e kërkimeve dhe kërkesat e performancës dhe mirëmbajtjes së projektit.
Kur filloni të punoni me Laravel dhe keni nevojë për një motor kërkimi në kohë reale që përgjigjet menjëherë , është e lehtë të humbisni midis një mijë qasjeve të mundshme: AJAX me fetch, jQuery, Alpine.js, Scout me Algolia ose Meilisearch, filtrim frontend, etj. Lajmi i mirë është se ekosistemi Laravel tashmë ofron praktikisht gjithçka që ju nevojitet për të ndërtuar një motor kërkimi të qetë dhe të shpejtë pa u mbingarkuar.
Në këtë artikull, do të mësoni se si të zbatoni lloje të ndryshme të kërkimit në kohë reale në Laravel , nga autocomplete klasike AJAX deri te kërkimet me tekst të plotë duke përdorur Laravel Scout dhe motorë kërkimi si Algolia, Meilisearch, vetë bazën e të dhënave, apo edhe Elasticsearch. Gjithashtu do të eksploroni alternativa të lehta me Alpine.js për filtrimin e të dhënave direkt në shfletues kur merreni me grupe të vogla të dhënash.
Çfarë është një kërkim në kohë reale në Laravel dhe si funksionojnë bazat?
Ideja që qëndron pas kërkimit në kohë reale është që, ndërsa përdoruesi shkruan në një fushë teksti , aktivizohet një pyetje dhe rezultatet përditësohen pa e ringarkuar faqen. Teknikisht, kjo përfshin tre komponentë kryesorë: backend-in e Laravel-it, JavaScript-in e shfletuesit dhe shkëmbimin e të dhënave në formatin JSON.
Nga njëra anë, Laravel vepron si shtresa e serverit përgjegjëse për marrjen e kërkesave, interpretimin e parametrave të kërkimit (tekstin e futur), pyetjet në bazën e të dhënave dhe kthimin e një përgjigjeje të strukturuar, zakonisht në formatin JSON. Kjo përgjigje mund të tregojë sukses, gabim ose që nuk u gjetën rezultate.
Në anën tjetër, JavaScript merret me dëgjimin e ngjarjeve të përdoruesit në hyrjen e kërkimit, dërgimin e kërkesave asinkrone (AJAX) në backend dhe paraqitjen e të dhënave të kthyera në faqe pa pasur nevojë për një rifreskim të plotë të shfletuesit. Kjo mund të bëhet me fetch native, jQuery AJAX ose biblioteka të vogla reaktive si Alpine.js.
Me këtë mekanizëm bazë, ju mund të ndërtoni çdo gjë, nga një plotësim automatik i thjeshtë me disa të dhëna , deri te një motor kërkimi me tekst të plotë të avancuar me rëndësi, faqezim dhe filtra, duke u mbështetur në biblioteka si Laravel Scout dhe motorë kërkimi të jashtëm të optimizuar për kërkime.
Modeli, rrugët dhe kontrolluesi për një motor kërkimi bazë në kohë reale
Para se të futeni thellë në JavaScript, duhet që ana e Laravel të jetë e organizuar mirë: një model Eloquent për të kërkuar, rrugë të qarta dhe një kontrollues i dedikuar për trajtimin e logjikës së kërkimit në kohë reale.
Hapi i parë është të keni një model Eloquent që përfaqëson tabelën ku do të kërkoni. Imagjinoni një tabelë vendesh dhe një model shumë të thjeshtë të quajtur Country , pa pulla kohore dhe me caktim masiv të lejuar:
Shembull i një modeli minimal Eloquent për kërkime :
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;
}
Kjo tregon që modeli Pais ndodhet në hapësirën standarde të emrave Laravel , trashëgon nga Model dhe lejon caktimin e çdo fushe me create() duke e lënë bosh vargun e mbrojtur. Duke çaktivizuar vulat kohore me public $timestamps = false, ju shmangni problemet nëse tabela nuk ka kolonat created_at dhe updated_at.
Hapi tjetër është përcaktimi i rrugëve që do të trajtojnë si shfaqjen e motorit të kërkimit ashtu edhe kërkesat AJAX . Një skemë shumë e zakonshme kombinon një rrugë GET për të shfaqur pamjen dhe një rrugë POST të projektuar për të marrë pyetje në kohë reale:
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']);
Rruga rrënjë kthen një pamje mirëseardhjeje, ndërsa URL-ja /search është e rezervuar për funksionalitetin e kërkimit . Metoda index() e kontrolluesit shfaq formularin dhe të dhënat hyrëse të kërkimit, ndërsa metoda search() përpunon kërkesat asinkrone të dërguara nga shfletuesi.
Në kontrollues mund të zbatoni një model shumë praktik: përgatitni një varg përgjigjesh të parazgjedhur në rast gabimi dhe mbishkruani atë vetëm kur është në të vërtetë një kërkesë e vlefshme AJAX dhe pyetja ekzekutohet pa probleme.
Kontrolluesi mund të ketë një strukturë të ngjashme me këtë:
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);
}
}
Në këtë pikë, keni ciklin e plotë të backend-it: kërkesën hyrëse AJAX, verifikimin se është me të vërtetë AJAX, pyetjen duke përdorur `where like` dhe kufizimin e numrit të rezultateve në një sasi të arsyeshme me `take(10)` për të shmangur mbingarkesën e bazës së të dhënave. Përgjigja dërgohet gjithmonë në JSON, gjë që e thjeshton shumë punën e frontend-it.
Pamja e Blade dhe marrja e JavaScript për kërkim reaktiv
Me modelin, rrugët dhe kontrolluesin gati, është koha për të ndërtuar pjesën e dukshme: një formular me një fushë kërkimi dhe një bllok për të shfaqur rezultatet , plus JavaScript përgjegjës për të bërë kërkesat në sfond.
Pamja Blade mund të jetë shumë e thjeshtë, duke u mbështetur në tokenin CSRF që Laravel injekton për të validuar kërkesat POST dhe në një input kërkimi që është i përshtatshëm për t’u përdorur:
<!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>
Në këtë shembull, skripti dëgjon për ngjarjen keyup në hyrjen e kërkimit , kështu që çdo shtypje tasti shkakton një kërkesë për marrjen e të dhënave në shtegun /search. Teksti aktual i fushës dërgohet në formatin JSON, dhe kokat e tasteve si X-Requested-With përfshihen për të treguar se është AJAX, së bashku me tokenin CSRF për të anashkaluar mbrojtjen vendase të Laravel.
Kur mbërrijë përgjigja, ajo transformohet në JSON dhe një listë e vogël HTML me rezultatet gjenerohet në mënyrë dinamike , ose shfaqet një mesazh si "Nuk u gjetën rezultate" nëse pyetja nuk kthen të dhëna. E gjithë kjo ndodh pa e ringarkuar faqen, në një mënyrë natyrale për përdoruesin.
Ky model mund të rafinohet më tej me detaje të vogla të UX-it, të tilla si shtimi i një debounce midis shtypjeve të tasteve, shfaqja e një ngarkuesi ose trajtimi i gabimeve të rrjetit për të parandaluar që ndërfaqja të shfaqet e ngrirë kur diçka dështon.
Kërkim i drejtpërdrejtë me Laravel dhe AJAX duke përdorur jQuery
Edhe pse fetch ka fituar terren të konsiderueshëm, jQuery AJAX mbetet shumë popullor në projektet e trashëguara ose ekipet që e kanë tashmë të integruar. Ideja është saktësisht e njëjtë: kapni atë që shkruan përdoruesi, bëni një kërkesë asinkrone dhe rifreskoni DOM-in.
Një rrjedhë tipike pune me jQuery në Laravel për një kërkim të drejtpërdrejtë zakonisht përfshin këto hapa bazë: përcaktoni një rrugë specifike, krijoni një kontrollues të dedikuar, ndërtoni pamjen Blade me të dhënat e kërkimit dhe së fundmi shtoni kodin jQuery që aktivizon AJAX ndërsa shtypet.
Procesi funksionon kështu: kur përdoruesi fillon të shkruajë, jQuery dërgon një pyetje në server me vargun e kërkimit. Laravel filtron informacionin në bazën e të dhënave, kthen një objekt JSON me rezultatet që përputhen dhe jQuery përditëson një kontejner HTML në faqe për të pasqyruar përputhjet, të gjitha brenda pak milisekondash.
Avantazhi i përdorimit të jQuery është se thjeshton shumë sintaksën AJAX dhe është shumë e lehtë për t’u lexuar nëse e keni tashmë bibliotekën në projektin tuaj. Megjithatë, ajo prezanton një varësi shtesë që mund të mos jetë e nevojshme nëse mund të punoni me JavaScript modern dhe funksionalitetin nativ të marrjes.
Filtrim dhe kërkim në kohë reale në frontend me Alpine.js
Kur të dhënat që do të shfaqen janë relativisht të vogla (për shembull, më pak se 50 artikuj ), nuk ia vlen gjithmonë të konfigurosh një backend me kërkime komplekse. Në këto raste, një opsion shumë i përshtatshëm është të filtrosh direkt në shfletues duke përdorur Alpine.js , pa bërë kërkesa në server ndërsa përdoruesi shkruan.
Ideja është që të llogaritet paraprakisht një varg kërkimi për secilin artikull (p.sh., emri, përshkrimi dhe kategoria me shkronja të vogla), të ruhet në një atribut data-search-text dhe të lejohet që Alpine.js të trajtojë shfaqjen ose fshehjen e artikujve bazuar në tekstin e futur në një fushë kërkimi.
Komponenti Alpine.js mund të ketë një strukturë të ngjashme me këtë: filterItems
{
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;
},
}
Në pamje, çdo kartë ose rresht i të dhënave do të kishte një atribut data-search-text me tekstin e përgatitur tashmë me shkronja të vogla , kështu që filtri reduktohet në një includes() në JavaScript, shumë shpejt për listat e shkurtra:
<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>
Për më tepër, mund të shfaqni një bllok statusi bosh vetëm kur nuk ka rezultate për termin aktual të kërkimit , duke e ftuar përdoruesin të modifikojë tekstin ose të pastrojë fushën me një buton që thjesht e rivendos kërkimin në një varg bosh.
Kjo qasje ka përparësi të qarta: nuk ka thirrje serveri gjatë kërkimit , ndërveprimi është praktikisht i menjëhershëm dhe logjika mbetet shumë lokale dhe e lehtë për t'u debuguar. Është perfekte për përzgjedhës të shpejtë, modale të përzgjedhjes së artikujve ose katalogë të vegjël të integruar në një faqe Laravel.
Laravel Scout: Kërkim me tekst të plotë me motorë të specializuar
Kur gjërat bëhen serioze dhe ju nevojitet një kërkim i shpejtë, relevant dhe i shkallëzueshëm me tekst të plotë , rruga natyrale në Laravel është Laravel Scout. Scout është një shtresë integrimi që ju lejon të lidhni lehtësisht modelet tuaja Eloquent me motorë kërkimi si Algolia, Meilisearch, bazën tuaj të të dhënave, koleksionet në memorie ose edhe Elasticsearch nëpërmjet kontrolluesve të jashtëm.
Për të filluar me Scout, qasja e zakonshme është të krijoni një projekt të ri Laravel ose të ripërdorni një ekzistues , ta nisni atë me Docker (për shembull, duke përdorur Laravel Sail) dhe pastaj të instaloni bibliotekën me Composer. Pasi të keni mbaruar këtë, publikoni skedarin e konfigurimit scout.php dhe rregulloni variablat e mjedisit sipas drajverit që dëshironi të përdorni.
Një rrjedhë tipike pune do të ishte instalimi i Scout me Composer, publikimi i konfigurimit të tij dhe aktivizimi i radhës së indeksimit me `SCOUT_QUEUE=true` në skedarin `.env` në mënyrë që operacionet që kërkojnë shumë burime të përpunohen në sfond, duke përmirësuar kohën e reagimit të aplikacionit. Përveç kësaj, duhet të siguroheni që `DB_HOST` të tregojë bazën e të dhënave që po përdorni, gjë që është veçanërisht e rëndësishme nëse përdorni kontejnerë Docker.
Që një model të marrë pjesë në kërkimet Scout, ai duhet të shënohet në mënyrë të qartë si i kërkueshëm duke shtuar tiparin `I kërkueshëm` . Për shembull, nëse keni një model `Tren` që përfaqëson një tabelë trenash me një fushë `titull`, mund ta përcaktoni atë si më poshtë:
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';
}
}
Metoda `searchableAs` ju lejon të personalizoni emrin e indeksit në motorin e kërkimit , në vend që të përdorni emrin e parazgjedhur të nxjerrë nga modeli. Prej andej, Scout trajton sinkronizimin e operacioneve të krijimit, përditësimit dhe fshirjes me indeksin e largët ose lokal, varësisht nga drajveri i zgjedhur.
Laravel Scout me Algolia: Kërkim SaaS me shpejtësi rrufeje
Algolia është një shërbim SaaS i fokusuar në ofrimin e kërkimeve shumë të shpejta dhe relevante në vëllime të mëdha të dhënash . Ai përmban një panel web për menaxhimin e indekseve, rregullave të relevancës, sinonimeve dhe më shumë, dhe integrohet pa probleme me Laravel nëpërmjet Scout dhe klientit zyrtar PHP.
Për të përdorur Algolia me Scout, do t'ju duhet të instaloni klientin e tij PHP duke përdorur Composer, të regjistroni kredencialet tuaja në skedarin .env (ID e Aplikacionit dhe Çelësi API i Administratorit) dhe të konfiguroni SCOUT_DRIVER=algolia për t'i thënë Scout të përdorë këtë motor. Mund të merrni si ID-në e aplikacionit ashtu edhe çelësin e administratorit nga paneli i Algolia-s.
Pasi të jetë konfiguruar mjedisi, mund të përdorni metoda si Train::search('text')->paginate(6) direkt në kontrolluesit tuaj për të kryer kërkime në fushat e indeksuara, duke marrë rezultate në formatin Eloquent të faqosur, gati për t'u kaluar në një pamje Blade.
Për shembull , mund të keni një kontrollues indeksi që liston të gjithë trenat ose kryen një kërkim nëse kalohet një parametër titlesearch, dhe një metodë create për të futur trena të rinj në indeks:
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();
}
Në pamjen përkatëse, mund të kombinoni një formular për shtimin e trenave të rinj dhe një formular tjetër GET me një fushë kërkimi për titullin që aktivizon kërkimin pas dorëzimit. Pastaj thjesht kaloni nëpër koleksionin e trenave dhe shfaqni fushat e tyre në një tabelë, duke përfituar nga lidhjet e faqezimit të gjeneruara nga Laravel.
Zbuloni me Meilisearch, bazën e të dhënave dhe koleksionet
Nëse preferoni të shmangni shërbimet e jashtme, Meilisearch është një motor kërkimi me burim të hapur që mund ta instaloni lokalisht ose në infrastrukturën tuaj. Scout integrohet me Meilisearch në një mënyrë shumë të ngjashme me Algolia, thjesht duke ndryshuar drajverin dhe duke shtuar variablat MEILISEARCH_HOST dhe MEILISEARCH_KEY në skedarin .env.
Për ta përdorur, instaloni klientin Meilisearch PHP, vendosni SCOUT_DRIVER=meilisearch dhe drejtoni MEILISEARCH_HOST te URL-ja e instancës (për shembull, http://127.0.0.1:7700). Nëse keni tashmë të dhëna, mund t'i indeksoni ato me komandën php artisan scout:import "App\Models\Train" në mënyrë që motori t'i ketë të disponueshme.
Për aplikacione më të vogla ose me madhësi mesatare, mund të zgjidhni edhe drajverin e bazës së të dhënave të Scout , i cili shfrytëzon indekset me tekst të plotë dhe deklaratat LIKE në bazën tuaj të të dhënave MySQL ose PostgreSQL. Në këtë rast, nuk keni nevojë për një shërbim të jashtëm; thjesht caktoni SCOUT_DRIVER=database që Scout të përdorë vetë bazën e të dhënave si motor kërkimi.
Një tjetër opsion interesant është drajveri i koleksionit, i cili funksionon me koleksionet Eloquent në memorie . Ky motor filtron rezultatet duke përdorur metodat `where` dhe filtrimin e koleksionit, dhe është i pajtueshëm me çdo bazë të dhënash të mbështetur nga Laravel. Mund ta aktivizoni me `SCOUT_DRIVER=collection` ose duke rregulluar skedarin e konfigurimit Scout nëse dëshironi diçka më specifike.
Integrimi me Elasticsearch duke përdorur Explorer
Nëse nevojat tuaja të kërkimit përfshijnë punën me vëllime të mëdha të dhënash dhe analiza në kohë reale , Elasticsearch është një klasik. Në ekosistemin Laravel, një mënyrë moderne për ta integruar atë me Scout është përdorimi i kontrolluesit Explorer, i cili vepron si një urë lidhëse midis modeleve tuaja dhe një klasteri Elasticsearch.
Kjo zakonisht përfshin punën me Docker dhe një skedar të pasur docker-compose që nis, përveç shërbimeve të zakonshme (Laravel, MySQL, Redis, Meilisearch, etj.), kontejnerët Elasticsearch dhe Kibana . Pastaj instaloni paketën jeroen-g/explorer nëpërmjet Composer dhe publikoni skedarin e tij të konfigurimit për të specifikuar se cilat modele duhet të indeksohen.
Në skedarin config/explorer.php, mund të regjistroni modelet tuaja nën çelësin e indekseve, për shembull duke shtuar App\Models\Train::class . Përveç kësaj, mund ta ndryshoni drajverin nga Scout në Elasticsearch në skedarin .env me SCOUT_DRIVER=elastic në mënyrë që gjithçka të tregojë te Elasticsearch.
Brenda modelit Train, duhet të implementoni ndërfaqen Explored dhe të mbivendosni metodën mappableAs , e cila përcakton hartën e fushave që do të dërgohen në indeks. Një shembull minimal do të ishte:
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,
];
}
}
Nga këtu, mund të nisni kërkime në Elasticsearch duke përdorur të njëjtën ndërfaqe Scout , duke përfituar nga kohët shumë të ulëta të përgjigjes dhe fuqia e plotë e pyetjeve të këtij motori, por pa dalë nga ekosistemi Laravel.
Me të gjitha këto qasje - nga plotësimi automatik bazë me fetch ose jQuery, te filtrimi i frontend me Alpine.js, te kërkimet me tekst të plotë me Laravel Scout dhe drajverë të ndryshëm - Laravel ju ofron një gamë të gjerë opsionesh për të zbatuar kërkime në kohë reale të përshtatura sipas madhësisë së projektit tuaj, performancës që ju nevojitet dhe infrastrukturës që jeni të gatshëm të mirëmbani.