Guia completa de cerca en temps real a Laravel

Darrera actualització: 5 de desembre de 2025
  • Laravel permet implementar des de cercadors simples amb AJAX fins a cerques de text complet avançades usant Laravel Scout i motors externs com Algolia, Meilisearch o Elasticsearch.
  • Per a cerques lleugeres, el filtratge al frontend amb Alpine.js o amb peticions fetch natives evita sobrecarregar el servidor i millora l'experiència d'usuari en llistes petites.
  • Laravel Scout centralitza la integració amb diferents motors de cerca i facilita marcar models com a cercables, gestionar índexs i llançar consultes de forma uniforme.
  • L'elecció del motor (SaaS, open source o base de dades) s'ha de basar en el volum de dades, la complexitat de les cerques i els requisits de rendiment i manteniment del projecte.

cerca en temps real a laravel

Quan comences a treballar amb Laravel i necessites un cercador en temps real que respongui al moment , és fàcil perdre's entre mil enfocaments possibles: AJAX amb fetch, jQuery, Alpine.js, Scout amb Algolia o Meilisearch, filtrat al frontend, etc. La bona notícia és que l'ecosistema de Laravel ja porta pràcticament tot el que necessites per muntar una cerca fluida i ràpida sense morir a l'intent.

En aquest article veuràs com muntar diferents tipus de cerca en temps real a Laravel , des del clàssic autocompletat amb AJAX fins a cerques de text complet amb Laravel Scout i motors com Algòlia, Meilisearch, la pròpia base de dades o fins i tot Elasticsearch. A més, veureu alternatives lleugeres amb Alpine.js per filtrar dades directament al navegador quan el volum d'informació és petit.

Què és una cerca en temps real a Laravel i com funciona la base

La idea d'una cerca en temps real és que, segons l'usuari escriviu en un camp de text , es dispari una consulta i s'actualitzin els resultats sense recarregar la pàgina. A nivell tècnic, això implica tres peces molt clares: el backend a Laravel, el JavaScript del navegador i l'intercanvi de dades en format JSON.

D'una banda, Laravel actua com la capa de servidor encarregada de rebre les peticions, interpretar els paràmetres de cerca (el text que s'escriu), consultar la base de dades i tornar una resposta estructurada, normalment a JSON. Aquesta resposta pot indicar èxit, error o que no s'han trobat resultats.

A l'altre extrem, JavaScript s'ocupa d'escoltar els esdeveniments de l'usuari sobre l'input de cerca, llançar peticions asíncrones (AJAX) al backend i pintar les dades retornades a la pàgina, sense que el navegador faci un refresc complet. Això es pot fer amb fetch nadiu, amb jQuery AJAX o amb petites llibreries reactives com Alpine.js.

Amb aquest mecanisme bàsic pots construir des d'un autocompletat senzill amb uns quants registres , fins a un cercador avançat de text complet amb rellevància, paginació i filtres, recolzant-te a llibreries com Laravel Scout i motors externs optimitzats per a cerques.

Model, rutes i controlador per a un cercador bàsic en temps real

Abans de ficar-te amb JavaScript, necessites que el costat de Laravel estigui ben organitzat: un model Eloquent sobre el qual cercar, rutes clares i un controlador dedicat a gestionar la lògica de la cerca en temps real.

El primer és disposar d'un model Eloquent que representi la taula on buscaràs. Imagina una taula de països i un model anomenat País molt senzill, sense marques de temps i amb assignació massiva permesa:

Exemple de model Eloquent mínim per a cerques :

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;
}

Aquí s'indica que el model País s'ubica a l'espai de noms estàndard de Laravel , hereta de Model i permet assignar qualsevol camp amb create() en deixar l'array guarded buit. En desactivar els timestamps amb public $timestamps = false, eviteu problemes si la taula no té les columnes created_at i updated_at.

El següent pas és definir les rutes que manejaran tant la visualització del cercador com les peticions AJAX . Un esquema molt habitual combina una ruta GET per mostrar la vista i una altra POST pensada per rebre les consultes en temps real:

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']);

La ruta arrel torna una vista de benvinguda, mentre que la URL /cercador es reserva per a la funcionalitat de cerca . El mètode index() del controlador mostra el formulari i l'input de cerca, mentre que el mètode cercar() processa les peticions asíncrones enviades des del navegador.

Al controlador pots implementar un patró molt pràctic: preparar un matriu de resposta per defecte en cas d'error i només sobreescriure'l quan efectivament es tracti d'una petició AJAX vàlida i la consulta s'executi sense problemes.

El controlador podria tenir una estructura similar a aquesta:

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);
}
}

En aquest punt ja tens el cicle backend complet: petició AJAX entrant, comprovació que és AJAX, consulta amb where like i limitació de resultats a un nombre raonable amb take(10) per no sobrecarregar la base de dades. La resposta s'envia sempre a JSON, cosa que simplifica molt la feina del frontend.

Vista Blade i JavaScript fetch per a una cerca reactiva

Amb el model, les rutes i el controlador llestos, toca construir la part visible: un formulari amb un camp de cerca i un bloc on mostrar els resultats , més el JavaScript encarregat de fer les peticions en segon pla.

La vista Blade pot ser molt senzilla, recolzant-se al token CSRF que Laravel injecta per validar les peticions POST i en un input de tipus search que resulta còmode d'usar:

<!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>

En aquest exemple, l'script escolta l'esdeveniment keyup sobre l'input de cerca , de manera que cada pulsació dispara una petició fetch cap a la ruta /cercador. S'envia el text actual del camp en format JSON i s'inclouen capçaleres clau com a X-Requested-With per indicar que és AJAX i el token CSRF per passar la protecció nativa de Laravel.

Quan arriba la resposta, es transforma en JSON i es genera dinàmicament un petit llistat HTML amb els resultats , o un missatge tipus “No hi ha resultats” quan la consulta no torna dades. Tot això sense recarregar la pàgina, de manera natural per a l'usuari.

Aquest patró es pot afinar encara més amb petits detalls de UX, com ara afegir un retard (debounce) entre pulsacions, mostrar un lloader o manejar errors de xarxa per evitar que la interfície sembli congelada quan alguna cosa falla.

Cerca en viu amb Laravel i AJAX usant jQuery

Encara que avui dia fetch ha guanyat molt de terreny, jQuery AJAX segueix sent molt popular en projectes legacy o en equips que ja el tenen incorporat. La idea és exactament la mateixa: capturar allò que l'usuari escriu, fer una petició asíncrona i refrescar el DOM.

Un flux de treball típic amb jQuery a Laravel per a una cerca en viu sol incloure aquests passos bàsics: definir una ruta específica, crear un controlador dedicat, construir la vista Blade amb l'input de cerca i finalment afegir el codi jQuery que dispari AJAX segons es tecleja.

El procés funciona així: quan lusuari comença a escriure, jQuery envia una consulta al servidor amb la cadena de cerca. Laravel filtra la informació en base de dades, torna un JSON amb els resultats coincidents i jQuery actualitza un contenidor HTML a la pàgina per reflectir les coincidències, tot en qüestió de mil·lisegons.

L'avantatge d'usar jQuery és que sintetitza força la sintaxi d'AJAX i és molt directe de llegir si ja tens la llibreria al teu projecte. A canvi, arrossegues una dependència addicional que potser no és necessària si pots treballar amb JavaScript modern i fetch nadiu.

Filtratge i cerca en temps real al frontend amb Alpine.js

Quan les dades a mostrar són relativament poques (per exemple, menys de 50 elements ), no sempre compensa muntar un backend amb cerques complexes. En aquests casos, una opció molt còmoda és filtrar directament al navegador amb Alpine.js sense fer peticions al servidor mentre l'usuari escriu.

La idea consisteix a precalcular una cadena de cerca per a cada element (per exemple, nom, descripció i categoria en minúscules), desar-la en un atribut data-search-text i deixar que Alpine.js s'encarregueu de mostrar o ocultar els elements segons el text escrit en un camp de cerca.

El component Alpine.js pot tenir una estructura semblant a aquesta: 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;
},
}

A la vista, cada targeta o fila de dades portaria un atribut data-search-text amb el text ja preparat en minúscules , de manera que el filtre es redueix a un includes() en JavaScript, molt ràpid per a llistes curtes:

<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>

A més, pots mostrar un bloc d'estat buit només quan no hi ha resultats per al terme actual de cerca , convidant a l'usuari a modificar el text o netejar el camp amb un botó que simplement reinicia search a cadena buida.

Aquest enfocament té avantatges clars: no hi ha trucades al servidor durant la cerca , la interacció és pràcticament instantània i la lògica es manté molt local i fàcil de depurar. És perfecte per a selectors ràpids, maneres de triar elements o petits catàlegs incrustats en una pàgina de Laravel.

Laravel Scout: cerca de text complet amb motors especialitzats

Quan la cosa es posa seriosa i necessites cerques de text complet ràpides, amb rellevància i escalables , el camí natural a Laravel és Laravel Scout. Scout és una capa d'integració que permet connectar de forma senzilla els teus models Eloquent amb motors de cerca com Algòlia, Meilisearch, la base de dades, col·leccions en memòria o fins i tot Elasticsearch a través de controladors externs.

Per començar amb Scout, el més habitual és crear un nou projecte Laravel o reutilitzar un existent , llançar-ho amb Docker (per exemple, usant Laravel Sail) i després instal·lar la llibreria amb Composer. Un cop fet això, publiques el fitxer de configuració scout.php i ajustes les variables d'entorn segons el driver que vulguis fer servir.

Un flux típic seria instal·lar Scout amb Composer, publicar-ne la configuració i activar la cua d'indexació amb SCOUT_QUEUE=true a l'arxiu .env perquè les operacions pesades es processin en segon pla, millorant els temps de resposta de l'aplicació. A més, has d'assegurar-te que DB_HOST apunti a la base de dades que estiguis usant, cosa especialment important si ets dins de contenidors Docker.

Perquè un model pugui participar en les cerques de Scout, cal marcar-lo explícitament com a cercable afegint el trait Searchable . Per exemple, si tens un model Train que representa una taula de trens amb un camp title, podries definir-ho així:

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';
}
}

El mètode searchableAs permet personalitzar el nom de l'índex al motor de cerca , en lloc de fer servir el nom per defecte derivat del model. A partir d´aquí, Scout s´encarrega de sincronitzar les operacions de creació, actualització i esborrat amb l´índex remot o local, segons el driver escollit.

Laravel Scout amb Algolia: cerca SaaS ultraràpida

Algolia és un servei SaaS centrat en oferir cerques molt ràpides i rellevants sobre grans volums de dades . Disposa d'un panell web per gestionar índexs, regles de rellevància, sinònims, etc., i s'integra molt bé amb Laravel mitjançant Scout i el client PHP oficial.

Per utilitzar Algòlia amb Scout hauràs d'instal·lar el seu client PHP amb Composer, registrar les teves credencials al fitxer .env (Application ID i Admin API Key) i configurar SCOUT_DRIVER=algòlia per indicar a Scout que faci servir aquest motor. Des del panell d'Algòlia podeu obtenir tant l'ID de l'aplicació com la clau administrativa.

Un cop configurat l'entorn, ja pots utilitzar mètodes com Train::search('texto')->paginate(6) directament als teus controladors per fer cerques sobre els camps indexats, rebent resultats en format Eloquent paginat llest per passar a una vista Blade.

Per exemple , podríeu tenir un controlador index que llisti tots els trens o apliqui cerca si arriba un paràmetre titlesearch, i un mètode create per inserir nous trens a l'índex:

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();
}

A la vista corresponent, podeu combinar un formulari per a alta de nous trens i un altre formulari GET amb un camp titlesearch que dispari la cerca en enviar. Després només has de recórrer la col·lecció de trens i mostrar els seus camps a una taula, aprofitant els enllaços de paginació generats per Laravel.

Scout amb Meilisearch, base de dades i col·leccions

Si preferiu evitar serveis externs, Meilisearch és un motor de cerca open source que podeu desplegar en local o en la vostra infraestructura. Scout s'integra amb Meilisearch de manera molt similar a Algòlia, canviant simplement el driver i afegint les variables MEILISEARCH_HOST i MEILISEARCH_KEY al .env.

Per utilitzar-lo, instal·les el client PHP de Meilisearch, ajustes SCOUT_DRIVER=meilisearch i apuntes MEILISEARCH_HOST a la URL de la instància (per exemple, http://127.0.0.1:7700). Si ja tenies registres previs, pots indexar-los amb l'ordre php artisan scout:import App\Models\Train perquè el motor els tingui disponibles.

En aplicacions més petites o moderades, també pots triar el driver database de Scout , que aprofita índexs de text complet i instruccions like sobre la base de dades MySQL o PostgreSQL. En aquest cas no necessites un servei extern, només cal establir SCOUT_DRIVER=database perquè Scout faci servir la pròpia base de dades com a motor de cerca.

Una altra opció interessant és el driver collection, que treballa sobre col·leccions Eloquent en memòria . Aquest motor filtra els resultats amb mètodes where i filtratge de col·leccions, i és compatible amb qualsevol base de dades suportada per Laravel. Pots activar-ho amb SCOUT_DRIVER=collection o ajustant el fitxer de configuració de Scout si vols alguna cosa més específica.

Integració amb Elasticsearch mitjançant Explorer

Si les teves necessitats de cerca passen per treballar amb volums enormes de dades i anàlisi en temps real , Elasticsearch és un clàssic. A l'ecosistema de Laravel, una forma moderna d'integrar-lo amb Scout és fer servir el controlador Explorer, que actua com a pont entre els teus models i un clúster d'Elasticsearch.

Per això, se sol treballar amb Docker i un arxiu docker-compose enriquit que aixeca, a més dels serveis típics (Laravel, MySQL, Redis, Meilisearch, etc.), contenidors d'Elasticsearch i Kibana . Després instal·les el paquet jeroen-g/explorer via Composer i publiques el seu fitxer de configuració per indicar quins models s'han d'indexar.

Al fitxer config/explorer.php pots registrar els teus models a la clau indexes, per exemple afegint App\Models\Train::class . A més, canvies el driver de Scout a elastic al fitxer .env amb SCOUT_DRIVER=elastic perquè tot apunti a Elasticsearch.

Dins del model Train cal implementar la interfície Explored i sobreescriure el mètode mappableAs , que defineix el mapa de camps que s'enviaran a l'índex. Un exemple mínim seria:

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,
];
}
}

A partir d'aquí, podeu llançar cerques sobre Elasticsearch usant la mateixa interfície de Scout , beneficiant-vos de temps de resposta molt baixos i de tota la potència de consultes d'aquest motor, però sense sortir de l'ecosistema Laravel.

Amb tots aquests enfocaments -des de l'autocompletat bàsic amb fetch o jQuery, passant per filtrat al frontend amb Alpine.js, fins a cerques de text complet amb Laravel Scout i diferents drivers- Laravel et dóna un ventall enorme d'opcions per implementar cerques en temps real adaptades a la mida del teu projecte, al rendiment que necessites ia la infraestructura.

  Com controlar bombetes Tuya de forma local a Home Assistant