Filtros con cláusulas condicionales, when y whereBetween en Laravel Livewire - Eloquent
Índice de contenido
Vamos a crear los filtros que implementamos antes mediante condicionales, pero ahora “modo Laravel”, que es el recomendado por el equipo de Laravel. La decisión final de cuál método emplear queda a criterio del lector.
Model::when(request('search'), function (Builder $query, string $search) ...Uso básico de when()
Para esto, utilizaremos el método when().
- El primer parámetro corresponde a la propiedad que se desea evaluar.
- Si el valor está definido, se ejecuta el segundo parámetro, que es un closure:
Model::when(request('search'), function (Builder $query, string $search) {
$query->where(function ($query) use ($search) {
$query-><WHERES>
})En este closure:
- $query permite aplicar cualquier operación con Eloquent.
- $search es el parámetro evaluado que se suministra al closure.
Uso de condicionales
Anteriormente, te mostré cómo usar condicionales clásicos con Laravel. Este es un ejemplo de mi implementación favorita:
public function render()
{
// $posts = Post::paginate(15);
// $posts = Post::where('id', '>=', 1);
$posts = new Post();
// $categories = Category::get();
$categories = Category::pluck("title", "id");
//filters
if ($this->type) {
$posts = $posts->where('type', $this->type);
}
if ($this->category_id) {
$posts = $posts->where('category_id', $this->category_id);
}
if ($this->posted) {
$posts = $posts->where('posted', $this->posted);
}
if ($this->search) {
$posts = $posts->where(function($query){
$query
->orWhere('id', 'like', '%'.$this->search.'%')
->orWhere('title', 'like', '%'.$this->search.'%')
->orWhere('description', 'like', '%'.$this->search.'%')
;
});
}
if ($this->from && $this->to) {
$posts = $posts->whereBetween('date', [date($this->from), date($this->to)]);
}
//filters
$posts = $posts->paginate(15);
return view('livewire.dashboard.post.index', compact('posts', 'categories'));
}Como puedes ver, es un enfoque funcional, pero ahora vamos a implementarlo usando when(), que es la forma oficial y recomendada por Laravel para aplicar condicionales.
$posts = Post::when($this->search, function (Builder $query, string $search) {
$query->where(function ($query) use ($search) {
$query->orWhere('id', 'like', "%" . $search . "%")
->orWhere('title', 'like', "%" . $search . "%")
->orWhere('description', 'like', "%" . $search . "%");
});
})Implementación usando when()
Partimos directamente del modelo y aplicamos los filtros opcionales de manera clara:
$posts = Post::when($this->search, function (Builder $query, string $search) {
$query->where(function ($query) use ($search) {
$query->orWhere('id', 'like', "%" . $search . "%")
->orWhere('title', 'like', "%" . $search . "%")
->orWhere('description', 'like', "%" . $search . "%");
});
})
->when($this->type, function(Builder $query, $type) {
$query->where('type', $type);
})
->when($this->category_id, function(Builder $query, $category_id) {
$query->where('category_id', $category_id);
})
->when($this->posted, function(Builder $query, $posted) {
$query->where('posted', $posted);
})
->when($this->type, function(Builder $query, $type) {
$query->where('type', $type);
})
->when($this->to, function(Builder $query, $to) use($from) {
$query->whereBetween('date', [date($from), date($this->to)]);
})->with('category')
->orderBy($this->sortColumn, $this->sortDirection)
->paginate(15);Cada filtro se aplica solo si existe el parámetro correspondiente.
El closure recibe los parámetros necesarios para aplicar las condiciones.
Filtros en la interfaz
La interfaz, la página web creada con blade y Laravel Livewire que acompaña estos filtros podría verse así:
<div class="grid grid-cols-2 gap-2 mb-3">
<select class="block w-full" wire:model.live='posted'>
<option value="">{{ __('Posted') }}</option>
<option value="not">{{ __('Not') }}</option>
<option value="yes">{{ __('Yes') }}</option>
</select>
<select class="block w-full" wire:model.live='type'>
<option value="">{{ __('Type') }}</option>
<option value="advert">{{ __('Advert') }}</option>
<option value="post">{{ __('Post') }}</option>
<option value="course">{{ __('Course') }}</option>
<option value="movie">{{ __('Movie') }}</option>
</select>
<select class="block w-full" wire:model.live='category_id'>
<option value="">{{ __('Category') }}</option>
@foreach ($categories as $i => $c)
<option value="{{ $i }}">{{ $c }}</option>
@endforeach
</select>
<x-input wire:model.live='search' placeholder="{{ __('Search...') }}" />
<div class="grid grid-cols-2 gap-2">
<x-input wire:model='from' placeholder="From" type='date' />
<x-input wire:model.live='to' placeholder="To" type='date' />
</div>
</div>En definitiva, el uso del método when no es mas que una consulta que se ejecutar de manera opcional si se cumple una condición de verdadero o falso.
El método when() permite ejecutar consultas de manera opcional, solo si se cumple una condición.
Esto hace que el código sea más limpio, legible y totalmente compatible con la filosofía de Laravel.
Filtrar por rangos de Fecha whereBetween
Otro filtro interesante es el que permite filtrar por rangos de fecha; para esto, vamos a usar dos campos para definir la cota inicial y final para el rango, y recuerda que es necesario convertir al tipo de dato correspondiente (fecha en este caso) para poder realizar las comparaciones correctamente desde el where():
app/Http/Controllers/Dashboard/PostController.php
//***
if (request('from') && request('to')) {
$posts->whereBetween('date', [date(request("from")), date(request("to"))]);
}
//***Desde el componente en Vue, creamos un par de campos de tipo fecha más para dichos rangos:
resources/js/Pages/Dashboard/Post/Index.vue
<TextInput class="w-full" type="date" placeholder="Date From" v-model="from" />
<TextInput class="w-full" type="date" placeholder="Date To" v-model="to" />
***
<script>
data() {
return {
confirmDeleteActive: false,
deletePostRow: "",
type: "",
category_id: "",
posted: "",
search: "",
from: "",
to: "",
};
},
***
router.get(
route("post.index", {
category_id: this.category_id,
type: this.type,
posted: this.posted,
search: this.search,
from: this.from,
to: this.to,
})
);
***
</script>En este ejemplo es un componente en Vue, pero, puedes usar una vista en blade de toda la vida.
Acepto recibir anuncios de interes sobre este Blog.
Vamos a aplicar los filtros definidos antes empleando los when y whereBetween, que es la manera predefinida en Laravel.