Laravel Query Scope is one of my favorite feature and its the one that I use extensively as it helps to keep code clean and make it more readable.
Let's suppose we have the following Code in Controller which fetches all the Posts which are active.
Post::query()
->where('active', 1)
->get();
A very simple query with one where clause. Let's convert this where Clause to a Scope. We will go to Post Model and will create a method. We will call it scopeActive
. The method name must being with scope
. It will have Eloquent\Builder passed to it automatically. So we will define our method like below:
public function scopeActive( $query )
{
return $query->where('active', 1);
}
We can now use utilize this Scope and our Controller Code will become as below:
Post::query()
->active()
->get();
We can now use our active
scope anywhere in our code and Laravel will automatically convert it into query. Not a big improvement, you might say, but let's look at the following example where we need to get Active Posts which are created between 2 dates.
Post::query()
->where('active', 1)
->whereBetween('created_at', [
$startDate . ' 00:00:00',
$endDate .' 23:59:59'
])
->get();
Let's create a scope for this. We will call it scopeBetween
and it will accept 2 parameters, $startDate
and $endDate
.
public function scopeBetween($query, $startDate, $endDate)
{
$endDate .= ' 23:59:59';
return $query->whereBetween('created_at', [
$startDate,
$endDate
]);
}
And now we can change our Controller Code as below:
Post::query()
->active()
->between($startDate, $endDate)
->get();
If we compare this, our code is much more readable and a lot of noise has been removed. And we are starting to see the benefit of using Scopes.
Let us have another scenario where we want to retrieve active Posts created during Last Month. Our Code without Scope would look like below:
Post::query()
->where('active', 1)
->whereBetween('created_at', [
Carbon::now()->startOfMonth()->subMonthNoOverflow(),
Carbon::now()->subMonthNoOverflow()->endOfMonth()
])
->get();
Now let us define a Scope as follows:
public function scopeLastMonth($query)
{
$startDate = Carbon::now()->startOfMonth()->subMonthNoOverflow();
$endDate = Carbon::now()->subMonthNoOverflow()->endOfMonth();
return $query->whereBetween('created_at', [
$startDate,
$endDate
]);
}
And our Code which uses the above scope becomes:
Post::query()
->active()
->lastMonth()
->get();
As you can see, we can encapsulate our complex or repeating conditions within the scope. We can give a meaningful name to our Scopes. And then use those scopes in our code which drastically improves the readability of our code.
Top comments (0)