Filters with conditional clauses, when and whereBetween in Laravel Livewire - Eloquent
Content Index
We are going to create the filters we implemented before using conditionals, but now in "Laravel mode," which is the one recommended by the Laravel team. The final decision on which method to use is up to the reader.
Model::when(request('search'), function (Builder $query, string $search) ...Basic usage of when()
For this, we will use the when() method.
- The first parameter corresponds to the property that you want to evaluate.
- If the value is defined, the second parameter, which is a closure, is executed:
Model::when(request('search'), function (Builder $query, string $search) {
$query->where(function ($query) use ($search) {
$query-><WHERES>
})In this closure:
- $query allows any operation with Eloquent to be applied.
- $search is the evaluated parameter supplied to the closure.
Usage of conditionals
Previously, I showed you how to use classic conditionals with Laravel. Here is an example of my favorite implementation:
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'));
}As you can see, it is a functional approach, but now we are going to implement it using when(), which is the official and recommended way by Laravel to apply conditionals.
$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 . "%");
});
})Implementation using when()
We start directly from the model and apply the optional filters clearly:
$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);Each filter is applied only if the corresponding parameter exists.
The closure receives the necessary parameters to apply the conditions.
Filters in the interface
The interface, the web page created with blade and Laravel Livewire that accompanies these filters, could look like this:
<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>Ultimately, the use of the when method is simply a query that is executed optionally if a true or false condition is met.
The when() method allows queries to be executed optionally, only if a condition is met.
This makes the code cleaner, more readable, and fully compatible with the Laravel philosophy.
Filter by whereBetween Date Ranges
Another interesting filter is the one that allows filtering by date ranges; for this, we will use two fields to define the initial and final limits for the range, and remember that it is necessary to convert to the corresponding data type (date in this case) in order to perform the comparisons correctly from the where():
app/Http/Controllers/Dashboard/PostController.php
//***
if (request('from') && request('to')) {
$posts->whereBetween('date', [date(request("from")), date(request("to"))]);
}
//***From the component in Vue, we create a couple more date fields for these ranges:
<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>In this example it's a component in Vue, but you can use a regular Blade view.
I agree to receive announcements of interest about this Blog.
We are going to apply the filters defined before using the when and whereBetween, which is the predefined way in Laravel.