Filtros de búsqueda en Laravel-Livewire
Tags: laravel, livewire, php, eloquent
Published: 2021-08-04 21:08:08

Una de las principales características que el usuario requiere cuando trabajamos con tablas es el filtrado de información en tiempo real.
En este post te enseñaré a crear diferentes filtros de búsqueda con el dinamismo que nos provee [Laravel-Livewire](https://laravel-livewire.com/).

##Instalación.
No nos detendremos a explicar la instalación de este framework es de lo mas sencillo; basta con seguir al pie de la letra la [documentación oficial](https://laravel-livewire.com/docs/2.x/installation).

##Universo del discurso.
Se tiene una pequeña app de películas que fueron dirigidas por uno o más directores de cine, lo que buscamos es mostrar la información de cada uno de las películas así como la de los directores de cine con __filtros de búsqueda.__
Para las películas los filtros necesarios son: Nombre de película y fecha de estreno.
Para los directores de cine los filtros necesarios son: Nombre del director.

##Manos a la obra.
Una vez entendido la situación a resolver empecemos a codificar.
Comenzaremos creando la estructura de la base de datos que podría lucir como la siguiente.

```
movies
    id - integer
    title- string 
    premiere - date

directors
    id - integer
    name - string
    
director_movie
    id - integer
    director_id - integer    
    movie_id - integer
```

Después crearemos modelos para cada entidad y agregaremos nuestras relaciones.
Modelo Director.

```
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Director extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
    ];
    /*
    * Relationships
    **/
    public function movies(){
        return $this->belongsToMany(Movie::class);
    }
}
```

Modelo Película
```
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Movie extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'premiere'
    ];
    /*
    * Relationships
    **/

    public function directors(){
        $this->belongsToMany(Director::class);
    }
}
```
> Nota: Para hacer el seed de mi base de datos estoy usando faker, posiblemente tú tengas información real así que no te preocupes por ello.

Ya que modelamos nuestra base de datos podremos crear nuestro componente usando el CLI de Artisan.

```
php artisan make:component IndexComponent
```

Deberá aparecer este nuevo componente en nuestra carpeta 
 > App\Http\Livewire\IndexComponent.php

Dentro del componente encontraremos el método render que mostrará el template de nuestro componente.

```
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class IndexComponent extends Component
{
    public function render()
    {
        return view('livewire.index-component');
    }
}
```

En esta vista es donde crearemos nuestra tabla para mostrar la información.
```

<div>
    <div class="table-responsive">
        <table class="table">
            <thead>
            <th>Nombre de película</th>
            <th>Premiere</th>
            <th>Director</th>
            </thead>
            <tbody>

            </tbody>
        </table>
    </div>
</div>
```
> Nota: Es imperativo contar con un div padre para todo componente de lo contrario encontraremos errores.

Antes de continuar tengo que platicarte que [Livewire](https://laravel-livewire.com/) nos brinda una API de acceso a propiedades dinámicas, especialmente para obtener información que se encuentra almacenada en una base de datos, esto se resume en las [Computed Properties](https://laravel-livewire.com/docs/2.x/properties).

Para crear una [computed property](https://laravel-livewire.com/docs/2.x/properties) es necesario crear un método que nos de acceso a ella y para lograrlo utilizaremos la siguiente nomenclatura

```
Utilizando el sufijo get[nuestra_propiedad]Property
public function getMoviesProperty(){
    // some magic code
}
```

siguiendo esta convención estamos listos para pasar a la parte importante de nuestro código.

Bien, hasta ahora nuestro controlador del componente luce de esta forma.

```
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class IndexComponent extends Component
{

    public function getMoviesProperty(){
        //Some magic code.
    }


    public function render()
    {
        return view('livewire.index-component');
    }
}
```

Es necesario crear nuestros filtros para realizar la búsqueda, en lo personal a mi me gusta abstraerlos en un array asociativo, déjame mostrarte como:

```
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class IndexComponent extends Component
{

    public $filters = [
        'movie_title' => '',
        'premiere' => '',
        'director_name' => '',
    ];
...
```
De está manera abstraemos todos los filtros en un solo array para realizar el [binding](https://laravel-livewire.com/docs/2.x/properties#data-binding) de nuestro array de filtros para esto también es necesario agregar los inputs en nuestro template.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6oanejjfi85r4du960ld.png)

Ahora a mostrar los datos del controlador del componente usando nuestra [computed property](https://laravel-livewire.com/docs/2.x/properties)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22fp5vs0kovoxv9ita65.png)

Permíteme explicarte línea por línea la idea del primer filtro que estamos haciendo.
- Indicamos que se hará un query al modelo Movie.
- Haciendo uso de las [clausulas condicionales](https://laravel.com/docs/8.x/queries#conditional-clauses) del query builder de Laravel el modelo entenderá cuando será necesario retornar alguna otra sentencia, es decir, cuando no se encuentre vacío el valor del índice movie_title retornará la sentencia where que se encuentra dentro de la [función anónima](https://www.php.net/manual/en/functions.anonymous.php) del método when; de lo contrario saltará a la siguiente instrucción.
- Agregamos el método [with](https://laravel.com/docs/8.x/eloquent-relationships#eager-loading) para evitar hacer demasiadas peticiones al servidor en las relaciones.

Ya que entendimos el flujo de información entre la vista del componente y el controlador del componente podremos realizar los demás filtros.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/577boj5gnk5tmiymrh9o.png)
Ahora bien; permíteme explicarte el funcionamiento del ultimo filtro que contiene la relación M:N de nuestra base de datos.
- Cuando no se encuentre vacío el valor del índice director_name retornara lo que se tenga dentro de la función anónima del método, así mismo haremos una unión entre las tablas con el método [whereHas](https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence) de esta manera podremos filtrar de manera correcta el nombre del director.

##Mostrando los datos
Finalmente solo queda mostrar los datos en la vista del componente de la siguiente manera.   

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sphtk2mhwtax6kwqj0vu.png)

##Es tu turno.
Hasta aquí hemos terminado el tutorial de como realizar los filtros de información en tiempo real, solo queda probarlo en tu maquina local y verás la magia.
Happy codding!