Crear un Buscador en Laravel Livewire

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!

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 orWhere() se compara el término también en el contenido del post.


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.