Guía Completa para crear un Buscador con Laravel Livewire
En el desarrollo web moderno, contar con búsquedas y filtros dinámicos en el frontend es casi una necesidad. Los usuarios esperan interfaces ágiles que les permitan encontrar información de forma sencilla.
Sin embargo, tradicionalmente agregar estas funcionalidades requería conocimientos avanzados de JavaScript y control del DOM. Esto complicaba y ralentizaba el trabajo de los programadores.
Es aquí donde entra Laravel Livewire, un excelente paquete desarrollado por Caleb Porzio que viene a resolver este problema. Livewire facilita enormemente la tarea de crear componentes dinámicos y actualizaciones en tiempo real, sin escribir JavaScript.
En este tutorial completo vamos a aprender cómo sacarle el máximo provecho a Livewire construyendo paso a paso un potente motor de búsqueda con filtrado en una aplicación Laravel.
Descubre cómo crear interfaces dinámicas de forma rápida y manteniendo un código organizado. ¡Comencemos!
Índice
Introducción a Laravel Livewire
Definición y características
Laravel Livewire es un paquete desarrollado por Caleb Porzio que facilita la creación de interfaces dinámicas sin tener que escribir JavaScript. Permite crear componentes reutilizables que actualizan partes específicas de la UI sin recargar la página completa.
Algunas de sus principales características son:
- Permite crear interfaces dinámicas sin usar JavaScript
- Los componentes renderizan vistas como respuesta a eventos del lado del servidor
- Utiliza AJAX para actualizar secciones específicas del DOM
- Fácil integración con Laravel
- Los componentes Livewire son reutilizables
- Tiene un ciclo de vida similar a cualquier componente JavaScript
Ventajas sobre Laravel normal
Algunas ventajas que tiene Livewire sobre Laravel son:
- No requiere conocimientos de JavaScript para crear interfaces dinámicas
- El código es más organizado al tener separada la lógica del componente
- Mejora el rendimiento al no recargar la página completa
- Los componentes son reutilizables en múltiples vistas
- Fácil de implementar y utilizar
Cuando debe usarse y cuando no
Livewire es ideal para:
- Crear interfaces dinámicas cuando no se requiere control total con JavaScript
- Cuando se quiere actualizar secciones específicas de la UI sin recargar la página
- Para desarrollo rápido de prototipos y MVPs
No es recomendable cuando:
- Se necesita un control total de la interacción con JavaScript
- Se trabaja en apps muy robustas que requieren manejo avanzado de estado
- La aplicación ya tiene una base de VueJS, React o Angular
Preparación del entorno
Para utilizar Livewire primero debe instalarse una aplicación Laravel. Para ello se ejecuta el comando:
composer create-project laravel/laravel livewire-search
Esto creará un proyecto Laravel en la carpeta "livewire-search".
Instalación paquete Livewire
Una vez creado el proyecto Laravel, se debe instalar el paquete de Livewire con Composer:
composer require livewire/livewire
Luego sólo queda publicar los assets con:
php artisan vendor:publish --tag=livewire
Configuración servidor desarrollo
Para trabajar cómodamente, lo ideal es configurar la aplicación para que se ejecute a través de un servidor de desarrollo en tiempo real. Podemos hacerlo con Laravel Valet o iniciando el servidor PHP interno.
Ejemplo levantando el servidor con Artisan:
php artisan serve
Con esto tendremos nuestro proyecto Laravel listo para comenzar a trabajar con Livewire.
Modelo Eloquent
Migración tabla de registros
Para guardar los datos que se van a mostrar en el buscador, primero necesitamos crear una tabla donde almacenarlos. En Laravel esto se hace fácilmente con migraciones.
Vamos a crear una migración para la tabla "posts":
php artisan make:migration create_posts_table
Luego definimos la estructura en el método up()
:
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
Finalmente ejecutamos la migración con:
php artisan migrate
Modelo para búsquedas
El siguiente paso es crear el modelo Eloquent para interactuar con esta tabla. Lo generamos con:
php artisan make:model Post
Y definimos la relación con la tabla "posts":
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $table = 'posts';
protected $fillable = [
'title',
'content',
];
}
Creando un Factory
Para poder crear un seeder de datos de prueba necesitamos configurar el factory del modelo Post. Primero creamos el Factory:
php artisan make:factory PostFactory
Con el factory lo configuramos con el título y el contenido del post alatorio:
public function definition(): array
{
return [
'title' => $this->faker->sentence(),
'content' => $this->faker->text(500),
];
}
Creando un Seeder
Para tener datos de prueba, vamos a crear un "seeder" de Laravel que nos permita insertar posts de ejemplo en la base de datos automáticamente. Primero generamos el seeder con Artisan:
php artisan make:seeder PostsSeeder
Esto creará la clase seeder en database/seeds/PostsSeeder.php
.
Dentro de este seeder definimos los datos falsos que queremos generar:
public function run(): void
{
\App\Models\Post::factory()->count(50)->create();
}
Finalmente, para ejecutar el seeder utilizamos el comando:
php artisan db:seed --class=PostsSeeder
Esto insertará los posts de prueba en la base de datos cada vez que queramos regenerar datos de testeo.
Ahora ya podemos enfocarnos en la lógica de Livewire sin preocuparnos por crear contenido de ejemplo manualmente. El seeder provee datos fakes rápidamente.
Componente Livewire
En este tutorial vamos a usar el componente livewire como una página al completo por lo tanto debemos crear el layout de livewire, si nosotros quisieramos que fuese parte de una web esto no haría falta.
php artisan livewire:layout
El layout que nos ha creado podremos verlo en resources/views/components/layouts/app.blade.php
Creación y rutas
Es el momento de crear nuestro primer componente Livewire. Lo hacemos con Artisan:
php artisan make:livewire SearchPosts
Esto genera un componente en la carpeta app/Http/Livewire
.
Ahora hay que definir una ruta para llegar a este componente. En web.php
:
Route::get('/search-posts', SearchPosts::class);
Funciones de consulta
Dentro del componente vamos a crear los métodos para buscar en la base de datos. Primero inyectamos el modelo Post y creamos la función render()
:
public function render()
{
return view('livewire.search-posts');
}
public function mount()
{
$this->posts = Post::all();
}
Luego el método para buscar:
public function search()
{
$this->posts = Post::where('title', 'LIKE', "%$this->searchTerm%")->get();
}
Puedes comprobar que hay una función mount
, esta función nos permite mostrar todos los posts una vez se ejecuta el componente.
Almacenar Input de Búsqueda
Crearmos una propiedad searchTerm
que almacenará lo que escribamos en el input de búsqueda:
public $searchTerm;
Retorno de resultados
Para retornar los resultados a la vista utilizamos la propiedad posts
que definimos.
public $posts;
Esta propiedad puede ser accedida desde la vista para mostrar los resultados.
Código Completo Componente Livewire
Así quedaría al completo nuestro componente livewire
<?php
namespace App\Livewire;
use App\Models\Post;
use Livewire\Component;
class SearchPosts extends Component
{
public $posts;
public $searchTerm;
public function render()
{
return view('livewire.search-posts');
}
public function mount()
{
$this->posts = Post::all();
}
public function search()
{
$this->posts = Post::where('title', 'LIKE', "%$this->searchTerm%")->get();
}
}
Vista del buscador
Es el turno de programar la interfaz con HTML y CSS. Nos dirigmos al archivo que hemos creado al crear el componente Livewire que se encuentra en resources/views/livewire/search-posts.blade.php
:
<div>
<input type="text" placeholder="Buscar..." wire:model="searchTerm" wire:keydown='search'>
<div>
@if ($posts->count() > 0)
<table>
@foreach ($posts as $post)
<tr>
<td>{{ $post->title }}</td>
</tr>
@endforeach
</table>
@else
<p>No hay resultados</p>
@endif
</div>
</div>
Caja de texto de búsqueda
El input que creamos tiene un wire:model
apuntando a la variable searchTerm
. Esto permite vincular ese campo de texto con el componente Livewire.
Cuando cambia el valor del input se disparará automáticamente el evento search()
dentro del componente.
Despliegue de resultados
Utilizamos la variable $posts
que contiene los resultados de la consulta para renderizarlos dentro de una tabla HTML. Si no hay resultados se muestra el mensaje "No hay resultados".
Lógica de búsqueda
La consulta que tenemos actualmente en el componente utiliza el operador LIKE de SQL:
$this->posts = Post::where('title', 'LIKE', "%$this->searchTerm%")->get();
Esto permite buscar coincidencias sin importar si el término está al inicio, final o en medio del título.
Es la forma más simple y rápida de agregar un buscador básico.
Búsqueda por multiples campos
Se puede expandir la búsqueda para que revise otros campos además del título:
$this->posts = Post::where('title', 'LIKE', "%$this->searchTerm%")
->orWhere('content', 'LIKE', "%$this->searchTerm%")
->get();
Con la función
Mostrar y paginar
Para agregar la paginación a nuestro componente Livewire necesitamos usar el paquete WithPagination
y despues ya podemos implementar paginación utilizando el método paginate()
:
<?php
namespace App\Livewire;
use App\Models\Post;
use Livewire\Component;
use Livewire\WithPagination;
class SearchPosts extends Component
{
use WithPagination;
public $searchTerm;
public function render()
{
// Si tenemos el input con datos lo filtramos
$posts = $this->searchTerm
? Post::where('title', 'LIKE', "%$this->searchTerm%")->paginate(10)
: Post::paginate(10);
return view('livewire.search-posts', ['posts' => $posts]);
}
// Re renderizamos el componente cuando escribimos en el input
public function search()
{
$this->render();
}
}
Esto devuelve una paginación de 10 resultados por página.
Podemos observar que hemos quitado el método mount
y ahora el método render
es el que muestra los datos en función de si hemos escrito datos en el input o no además de que la función search ha cambiado ahora cuando escribimos en el input de búsqueda vuelve a renderizar la vista
Luego en la vista se itera con @foreach
y se muestran los links de paginación:
<div>
<input type="text" placeholder="Buscar..." wire:model="searchTerm" wire:keydown='search'>
<div>
@if (count($posts) > 0)
<table>
@foreach ($posts as $post)
<tr>
<td>{{ $post->title }}</td>
</tr>
@endforeach
</table>
{{ $posts->links() }}
@else
<p>No hay resultados</p>
@endif
</div>
</div>
La sección de $posts->links()
nos muestra la paginación en tiempo de ejecución, es decir, variará en función de los elementos que busquemos
Conclusión
En este artículo vimos paso a paso cómo crear un buscador en Laravel utilizando Livewire y Eloquent de forma rápida y sencilla, sin necesidad de JavaScript.
Primero preparamos la base de datos, luego creamos el componente Livewire para manejar la lógica y por último diseñamos una interface en la vista con capacidad de actualización dinámica.
Posibles Mejoras:
Algunas mejoras que se le podrían hacer al buscador son:
- Agregar más filtros de búsqueda avanzados
- Opción de búsqueda por rangos de fechas
- Autocompletado de términos de búsqueda
- indexar los campos de búsqueda para mejor rendimiento
Preguntas Frecuentes
Sí, Laravel Livewire se puede integrar fácilmente en aplicaciones Laravel ya creadas agregando el paquete vía Composer.
No, una de las ventajas es precisamente que no necesita saber JavaScript. Todo se maneja del lado de Laravel.