Easily Use Laravel Query Scopes

Muhammad AR Zihad
3 min readJan 1, 2022

Let’s imagine a simple scenario:

You are a great web developer. You are building a project where you support multiple languages and currencies. There is an option for your users to choose their preferred language and currency from a huge list to use your application. Also, there are admins who can add more languages and currencies to the system. They can also disable specific languages and currencies if they want. You want to show your users only those languages and currencies which are currently active/enabled.

So how do you do it? There are multiple ways to do it. You can use softdeletes() or you can use your own database field ex. ‘active’/ ‘publish’/ ‘status’ as a flag. Let’s use the second approach. Why not the first approach? I’ll tell you later.

We will have a database like this:

languages
— name (string)
— short_name (string)
— status (bool)

currencies
— name (string)
— symbol (string)
— status (bool)

And this is how we return the lists:

Now if we look at the code then we will see that the where() clause is the same for both queries. You may have more tables similar to the languages and currencies table. And the where() clause will be the same for them too. So the same clause is getting repeated again and again.

So, how do we make this better?

Here Laravel query scope comes into play. If you need the same logic for many different queries then query scope is the way to go. You can extract a part of your query and put it in your model to simplify your query in the controller. Laravel offers both global and local scopes.

Using global scope

First, create a class in App\Scopes which implements Illuminate\Database\Eloquent\Scope interface.

app/Scopes/ActiveScope.php

Now assign the scope to your models (here: Language, Currency)

Do the same for other models(Currency). After that our eloquent query will look like this:

Returns all active languages and currencies
Remove scope for a specific query

This will return us all the entries that are active. By the way, we could’ve obtained the same result by using softdeletes(). softdeletes() itself is a scope provided by laravel. There is no specific reason behind why I didn’t use softdeletes(). I just wanted to make my own scope🤓 .

Using local scope

Now, what if you have a Category and a Post model which contains a field ‘status’ which can contain any of these values published/draft/pending. We can solve this by passing a parameter to our scope. But the problem is you can not pass dynamic parameters to the global scope. So, we will have to use local scope.

We can assign multiple local scopes to our model and chain the scopes to get expected results.

More scopes

There are more scopes that you can use.

— Anonymous Global Scope: This allows you to define global scope using closure inside your model.

Thank you very much for reading this post. I hope you get benefits from this post. Please feel free to share your thoughts and suggestions.

--

--