- Binibigyang-daan ka ng Laravel na ipatupad ang lahat mula sa mga simpleng search engine na may AJAX hanggang sa mga advanced na full-text na paghahanap gamit ang Laravel Scout at mga panlabas na search engine tulad ng Algolia, Meilisearch, o Elasticsearch.
- Para sa magaan na paghahanap, ang pag-filter sa frontend gamit ang Alpine.js o gamit ang mga native na kahilingan sa pagkuha ay maiiwasan ang labis na karga sa server at pinapahusay ang karanasan ng user sa maliliit na listahan.
- Isinasentro ng Laravel Scout ang pagsasama sa iba't ibang search engine at ginagawang madali na markahan ang mga modelo bilang mahahanap, pamahalaan ang mga index, at ilunsad ang mga query nang pantay-pantay.
- Ang pagpili ng engine (SaaS, open source o database) ay dapat na nakabatay sa dami ng data, ang pagiging kumplikado ng mga paghahanap at ang pagganap at pagpapanatili ng mga kinakailangan ng proyekto.
Kapag nagsimula kang gumamit ng Laravel at kailangan mo ng real-time search engine na agad na tutugon , madaling maligaw sa libu-libong posibleng paraan: AJAX na may fetch, jQuery, Alpine.js, Scout na may Algolia o Meilisearch, frontend filtering, atbp. Ang magandang balita ay ang Laravel ecosystem ay nagbibigay na ng halos lahat ng kailangan mo para makabuo ng maayos at mabilis na search engine nang hindi nalulula.
Sa artikulong ito, matututunan mo kung paano ipatupad ang iba't ibang uri ng real-time search sa Laravel , mula sa klasikong AJAX autocomplete hanggang sa full-text searches gamit ang Laravel Scout at mga search engine tulad ng Algolia, Meilisearch, ang database mismo, o kahit ang Elasticsearch. Matutuklasan mo rin ang mga magaan na alternatibo gamit ang Alpine.js para sa direktang pag-filter ng data sa browser kapag gumagamit ng maliliit na dataset.
Ano ang isang real-time na paghahanap sa Laravel at paano gumagana ang mga pangunahing kaalaman?
Ang ideya sa likod ng real-time search ay, habang nagta-type ang user sa isang text field , isang query ang nati-trigger at ina-update ang mga resulta nang hindi nire-reload ang pahina. Sa teknikal na aspeto, kinabibilangan ito ng tatlong pangunahing bahagi: ang Laravel backend, ang JavaScript ng browser, at ang pagpapalitan ng data sa JSON format.
Sa isang banda, ang Laravel ay gumaganap bilang server layer na responsable sa pagtanggap ng mga kahilingan, pagbibigay-kahulugan sa mga parameter ng paghahanap (ang tekstong ipinasok), pag-query sa database, at pagbabalik ng isang nakabalangkas na tugon, kadalasan sa format na JSON. Ang tugon na ito ay maaaring magpahiwatig ng tagumpay, error, o walang natagpuang resulta.
Sa kabilang dulo, pinangangasiwaan ng JavaScript ang pakikinig para sa mga kaganapan ng user sa input ng paghahanap, pagpapadala ng mga asynchronous request (AJAX) sa backend, at pag-render ng ibinalik na data sa pahina nang hindi nangangailangan ng buong pag-refresh ng browser. Magagawa ito gamit ang native fetch, jQuery AJAX, o maliliit na reactive library tulad ng Alpine.js.
Gamit ang pangunahing mekanismong ito, makakabuo ka ng kahit ano mula sa isang simpleng autocomplete na may ilang record , hanggang sa isang advanced na full-text search engine na may relevance, pagination, at mga filter, na umaasa sa mga library tulad ng Laravel Scout at mga external search engine na na-optimize para sa mga paghahanap.
Modelo, ruta, at controller para sa isang pangunahing real-time na search engine
Bago ka sumisid sa JavaScript, kailangan mo munang maging maayos ang Laravel side: isang Eloquent model na hahanapan, malinaw na mga ruta, at isang controller na nakatuon sa paghawak ng search logic sa real time.
Ang unang hakbang ay ang pagkakaroon ng isang Eloquent model na kumakatawan sa talahanayan kung saan ka maghahanap. Isipin ang isang talahanayan ng mga bansa at isang napakasimpleng modelo na tinatawag na Country , na walang mga timestamp at pinapayagan ang bulk assignment:
Halimbawa ng isang minimal na modelo ng Eloquent para sa mga paghahanap :
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;
}
Ipinapahiwatig nito na ang modelong Pais ay matatagpuan sa karaniwang namespace ng Laravel , nagmamana mula sa Model, at nagpapahintulot sa pagtatalaga ng anumang field na may create() sa pamamagitan ng pag-iwang walang laman ang guarded array. Sa pamamagitan ng pag-disable ng mga timestamp na may pampublikong $timestamps = false, maiiwasan mo ang mga problema kung ang talahanayan ay walang mga column na created_at at updated_at.
Ang susunod na hakbang ay ang pagtukoy ng mga ruta na hahawak sa parehong display ng search engine at mga kahilingan ng AJAX . Pinagsasama ng isang napakakaraniwang pamamaraan ang isang GET route upang ipakita ang view at isang POST route na idinisenyo upang makatanggap ng mga query sa real time:
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']);
Ang root route ay nagbabalik ng welcome view, habang ang /search URL ay nakalaan para sa search functionality . Ipinapakita ng index() method ng controller ang form at search input, habang pinoproseso naman ng search() method ang mga asynchronous request na ipinadala mula sa browser.
Sa controller, maaari kang magpatupad ng isang napaka-praktikal na pattern: maghanda ng isang default na response array kung sakaling magkaroon ng error at i-overwrite lamang ito kapag ito ay talagang isang wastong AJAX request at ang query ay isinasagawa nang walang problema.
Ang controller ay maaaring magkaroon ng istraktura na katulad nito:
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);
}
}
Sa puntong ito, mayroon ka nang kumpletong backend cycle: papasok na AJAX request, beripikasyon na ito nga ay AJAX, query gamit ang `where like`, at paglimita sa bilang ng mga resulta sa makatwirang dami gamit ang `take(10)` upang maiwasan ang labis na pag-load sa database. Ang tugon ay palaging ipinapadala sa JSON, na lubos na nagpapadali sa trabaho ng frontend.
Blade view at JavaScript fetch para sa reaktibong paghahanap
Kapag handa na ang modelo, mga ruta, at controller, oras na para buuin ang nakikitang bahagi: isang form na may search field at isang block para ipakita ang mga resulta , kasama ang JavaScript na responsable sa paggawa ng mga kahilingan sa background.
Ang Blade view ay maaaring maging napakasimple, umaasa sa CSRF token na ini-inject ng Laravel upang mapatunayan ang mga POST request at sa isang search input na madaling gamitin:
<!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>
Sa halimbawang ito, pinakikinggan ng script ang keyup event sa search input , kaya ang bawat keystroke ay nagti-trigger ng fetch request papunta sa /search path. Ang kasalukuyang teksto ng field ay ipinapadala sa JSON format, at ang mga key header tulad ng X-Requested-With ay kasama upang ipahiwatig na ito ay AJAX, kasama ang CSRF token upang malampasan ang native protection ng Laravel.
Kapag dumating ang tugon, ito ay binabago sa JSON at isang maliit na listahan ng HTML na may mga resulta ang dynamic na nabubuo , o isang mensahe tulad ng "Walang nahanap na resulta" ang ipapakita kung ang query ay walang ibinalik na data. Nangyayari ang lahat ng ito nang hindi nire-reload ang pahina, sa natural na paraan para sa user.
Ang pattern na ito ay maaaring higit pang pinuhin gamit ang maliliit na detalye ng UX, tulad ng pagdaragdag ng debounce sa pagitan ng mga keystroke, pagpapakita ng loader, o paghawak ng mga error sa network upang maiwasan ang paglitaw ng interface na nagyelo kapag may nabigo.
Live na paghahanap sa Laravel at AJAX gamit ang jQuery
Bagama't nakamit na ng malaking impluwensya ang fetch, nananatiling napakapopular ng jQuery AJAX sa mga legacy project o team na mayroon na nito. Pareho lang ang ideya: kunin ang tina-type ng user, gumawa ng asynchronous request, at i-refresh ang DOM.
Ang isang tipikal na daloy ng trabaho gamit ang jQuery sa Laravel para sa isang live na paghahanap ay karaniwang kinabibilangan ng mga pangunahing hakbang na ito: tukuyin ang isang partikular na ruta, lumikha ng isang nakalaang controller, buuin ang Blade view gamit ang search input , at panghuli ay idagdag ang jQuery code na magti-trigger sa AJAX habang ito ay tinatype.
Ganito ang proseso: kapag nagsimulang mag-type ang user, magpapadala ang jQuery ng query sa server gamit ang search string. Sinasala ng Laravel ang impormasyon sa database, nagbabalik ng JSON object na may katugmang resulta, at ina-update ng jQuery ang isang HTML container sa pahina upang maipakita ang mga tugma, lahat sa loob lamang ng ilang millisecond.
Ang bentahe ng paggamit ng jQuery ay lubos nitong pinapasimple ang syntax ng AJAX at napakadaling basahin kung mayroon ka nang library sa iyong proyekto. Gayunpaman, nagpapakilala ito ng karagdagang dependency na maaaring hindi kinakailangan kung maaari kang gumamit ng modernong JavaScript at native fetch functionality.
Real-time na pag-filter at paghahanap sa frontend gamit ang Alpine.js
Kapag ang datos na ipapakita ay medyo maliit (halimbawa, wala pang 50 aytem ), hindi palaging sulit na mag-set up ng backend na may mga kumplikadong paghahanap. Sa mga kasong ito, isang napaka-maginhawang opsyon ang direktang mag-filter sa browser gamit ang Alpine.js , nang hindi gumagawa ng mga kahilingan sa server habang nagta-type ang user.
Ang ideya ay ang paunang kalkulahin ang isang search string para sa bawat item (hal., pangalan, deskripsyon, at kategorya sa maliliit na titik), i-save ito sa isang data-search-text attribute, at hayaan ang Alpine.js na pangasiwaan ang pagpapakita o pagtatago ng mga item batay sa tekstong ipinasok sa isang search field.
Ang bahaging Alpine.js ay maaaring magkaroon ng istrukturang katulad nito: 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;
},
}
Sa view, ang bawat card o row ng data ay magkakaroon ng data-search-text attribute na may tekstong nakahanda na sa lowercase , kaya ang filter ay nagiging includes() sa JavaScript, napakabilis para sa mga maiikling listahan:
<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>
Bukod pa rito, maaari ka lamang magpakita ng walang laman na status block kapag walang resulta para sa kasalukuyang termino para sa paghahanap , na nag-aanyaya sa user na baguhin ang teksto o i-clear ang field gamit ang isang button na magre-reset lang sa paghahanap sa isang walang laman na string.
Ang pamamaraang ito ay may malinaw na mga bentahe: walang mga tawag sa server habang naghahanap , ang interaksyon ay halos agaran, at ang lohika ay nananatiling lubos na lokal at madaling i-debug. Perpekto ito para sa mga mabilisang selector, mga modal sa pagpili ng item, o maliliit na katalogo na naka-embed sa isang pahina ng Laravel.
Laravel Scout: Full-text na paghahanap gamit ang mga espesyal na makina
Kapag naging seryoso ang mga bagay-bagay at kailangan mo ng mabilis, may kaugnayan, at nasusukat na full-text search , ang natural na landas sa Laravel ay ang Laravel Scout. Ang Scout ay isang integration layer na nagbibigay-daan sa iyong madaling ikonekta ang iyong mga Eloquent model sa mga search engine tulad ng Algolia, Meilisearch, iyong sariling database, mga in-memory collection, o kahit ang Elasticsearch sa pamamagitan ng mga external controller.
Para makapagsimula sa Scout, ang karaniwang paraan ay ang paggawa ng bagong proyekto sa Laravel o muling paggamit ng dati nang proyekto , ilunsad ito gamit ang Docker (halimbawa, gamit ang Laravel Sail), at pagkatapos ay i-install ang library gamit ang Composer. Kapag tapos na iyon, ilalathala mo ang scout.php configuration file at iaakma ang mga environment variable ayon sa driver na gusto mong gamitin.
Ang isang karaniwang daloy ng trabaho ay ang pag-install ng Scout gamit ang Composer, paglalathala ng configuration nito, at pag-enable ng indexing queue gamit ang `SCOUT_QUEUE=true` sa `.env` file upang ang mga operasyong nangangailangan ng maraming mapagkukunan ay maproseso sa background, na magpapabuti sa oras ng pagtugon ng application. Bukod pa rito, dapat mong tiyakin na ang `DB_HOST` ay nakaturo sa database na iyong ginagamit, na lalong mahalaga kung gumagamit ka ng mga Docker container.
Para makasali ang isang modelo sa mga paghahanap sa Scout, dapat itong tahasang markahan bilang mahahanap sa pamamagitan ng pagdaragdag ng katangiang `Mahahanap` . Halimbawa, kung mayroon kang modelong `Tren` na kumakatawan sa isang talahanayan ng mga tren na may patlang na `title`, maaari mo itong tukuyin tulad nito:
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';
}
}
Ang pamamaraang `searchableAs` ay nagbibigay-daan sa iyong i-customize ang pangalan ng index sa search engine , sa halip na gamitin ang default na pangalan na hinango mula sa modelo. Mula doon, pinangangasiwaan ng Scout ang pag-synchronize ng mga operasyon sa paglikha, pag-update, at pagtanggal gamit ang remote o lokal na index, depende sa napiling driver.
Laravel Scout with Algolia: SaaS Search na napakabilis ng kidlat
Ang Algolia ay isang serbisyong SaaS na nakatuon sa pagbibigay ng napakabilis at may-katuturang mga paghahanap sa malalaking volume ng data . Nagtatampok ito ng web panel para sa pamamahala ng mga index, mga panuntunan sa kaugnayan, mga kasingkahulugan, at higit pa, at maayos na isinasama sa Laravel sa pamamagitan ng Scout at ng opisyal na PHP client.
Para magamit ang Algolia kasama ang Scout, kakailanganin mong i-install ang PHP client nito gamit ang Composer, irehistro ang iyong mga kredensyal sa .env file (Application ID at Admin API Key), at i-configure ang SCOUT_DRIVER=algolia para sabihin sa Scout na gamitin ang engine na ito. Makukuha mo ang parehong application ID at admin key mula sa Algolia dashboard.
Kapag na-set up na ang environment, maaari mong gamitin ang mga method tulad ng Train::search('text')->paginate(6) nang direkta sa iyong mga controller upang magsagawa ng mga paghahanap sa mga naka-index na field, na makakatanggap ng mga resulta sa naka-paginate na Eloquent format na handa nang ipasa sa isang Blade view.
Halimbawa , maaari kang magkaroon ng index controller na naglilista ng lahat ng train o nagsasagawa ng paghahanap kung may naipasa na parameter na titlesearch, at isang create method para magpasok ng mga bagong train sa index:
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();
}
Sa katumbas na view, maaari mong pagsamahin ang isang form para sa pagdaragdag ng mga bagong tren at isa pang GET form na may field para sa paghahanap ng pamagat na magti-trigger sa paghahanap pagkatapos isumite. Pagkatapos ay gagawa ka lang ng mga iteration sa koleksyon ng mga tren at ipapakita ang kanilang mga field sa isang table, gamit ang mga pagination link na nabuo ng Laravel.
Scout na may Meilisearch, database at mga koleksyon
Kung mas gusto mong iwasan ang mga panlabas na serbisyo, ang Meilisearch ay isang open-source search engine na maaari mong i-deploy nang lokal o sa iyong imprastraktura. Ang Scout ay nakikipag-ugnayan sa Meilisearch sa halos kaparehong paraan ng Algolia, sa pamamagitan lamang ng pagpapalit ng driver at pagdaragdag ng mga variable na MEILISEARCH_HOST at MEILISEARCH_KEY sa .env file.
Para magamit ito, i-install ang Meilisearch PHP client, itakda ang SCOUT_DRIVER=meilisearch , at ituro ang MEILISEARCH_HOST sa URL ng instance (halimbawa, http://127.0.0.1:7700). Kung mayroon ka nang mga record, maaari mo itong i-index gamit ang command na php artisan scout:import "App\Models\Train" para maging available ang mga ito sa engine.
Para sa mas maliliit o katamtamang laki ng mga aplikasyon, maaari mo ring piliin ang database driver ng Scout , na gumagamit ng mga full-text index at LIKE statement sa iyong MySQL o PostgreSQL database. Sa kasong ito, hindi mo kailangan ng panlabas na serbisyo; itakda lamang ang SCOUT_DRIVER=database para magamit ng Scout ang database mismo bilang search engine nito.
Isa pang kawili-wiling opsyon ay ang collection driver, na gumagana sa mga in-memory na Eloquent collection . Sinasala ng engine na ito ang mga resulta gamit ang `where` at mga paraan ng pagsala ng koleksyon, at tugma ito sa anumang database na sinusuportahan ng Laravel. Maaari mo itong i-activate gamit ang `SCOUT_DRIVER=collection` o sa pamamagitan ng pagsasaayos ng Scout configuration file kung gusto mo ng mas espesipiko.
Pagsasama sa Elasticsearch gamit ang Explorer
Kung ang iyong mga pangangailangan sa paghahanap ay kinabibilangan ng paggamit ng napakalaking dami ng data at real-time analytics , ang Elasticsearch ay isang klasiko. Sa ecosystem ng Laravel, ang isang modernong paraan upang maisama ito sa Scout ay ang paggamit ng Explorer controller, na nagsisilbing tulay sa pagitan ng iyong mga modelo at ng isang Elasticsearch cluster.
Karaniwang kinabibilangan ito ng pagtatrabaho gamit ang Docker at isang rich docker-compose file na naglulunsad, bilang karagdagan sa mga karaniwang serbisyo (Laravel, MySQL, Redis, Meilisearch, atbp.), Elasticsearch at Kibana containers . Pagkatapos ay i-install mo ang jeroen-g/explorer package sa pamamagitan ng Composer at ilalathala ang configuration file nito upang tukuyin kung aling mga modelo ang dapat i-index.
Sa config/explorer.php file, maaari mong irehistro ang iyong mga modelo sa ilalim ng indexes key, halimbawa sa pamamagitan ng pagdaragdag ng App\Models\Train::class . Bukod pa rito, babaguhin mo ang driver mula Scout patungong Elasticsearch sa .env file gamit ang SCOUT_DRIVER=elastic upang ang lahat ay tumuro sa Elasticsearch.
Sa loob ng modelo ng Train, kailangan mong ipatupad ang Explored interface at i-override ang mappableAs method , na siyang tumutukoy sa mapa ng mga field na ipapadala sa index. Ang isang minimal na halimbawa ay:
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,
];
}
}
Mula rito, maaari kang maglunsad ng mga paghahanap sa Elasticsearch gamit ang parehong Scout interface , na makikinabang sa napakababang oras ng pagtugon at sa buong lakas ng query ng engine na ito, ngunit nang hindi umaalis sa ecosystem ng Laravel.
Sa lahat ng mga pamamaraang ito—mula sa basic autocomplete gamit ang fetch o jQuery, hanggang sa frontend filtering gamit ang Alpine.js, hanggang sa full-text searches gamit ang Laravel Scout at iba't ibang drivers— binibigyan ka ng Laravel ng malawak na hanay ng mga opsyon para ipatupad ang mga real-time searches na iniayon sa laki ng iyong proyekto, sa performance na kailangan mo, at sa imprastraktura na handa mong panatilihin.