One of the best feature Laravel have is Laravel Eloquent ORM. Using Eloquent ORM is easy and it can makes our query simpler, cleaner than Query Builder but sometimes it can also be so long, and maybe we need to reuse the query too.
Is it possible to create a reusable query in Laravel Eloquent ORM?
Laravel Query Scope
We can use query scope to achieve the above situation. Here i will explain about the Laravel Local Scope.
For example if we want to get only the post that is currently marked as non-draft or published, we can use this query:
$publishedPosts = Post::where('is_draft', false)->get();
But I need to use this query in some places, not just in a place. And I don’t want to write this everytime I need it because it is quite long. Then we need to create a query scope for this.
Simple Scope
Create a method inside your model and insert above query to it, name the method with scope
prefix like so
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function scopePublished($query)
{
return $query->where('is_draft', false);
}
}
Now we have created the scope. However, we should not include the scope prefix when calling the method.
use App\Models\Post;
$publishedPosts = Post::published()->get();
Now it is more readable, shorter, and reusable. Even you can chain calls scopes for example if you have a popular
scope you can chain it like so
use App\Models\Post;
$popularPublishedPosts = Post::published()->popular()->get();
Read also:
Dynamic Scope
We can also create a scope that accepts parameters like so
class User extends Model {
public function scopeActive($query, $value)
{
return $query->where('is_active', $value);
}
}
Now we can use the scope dynamically
// Get active users
$activeUsers = User::active(true)->get();
// Get inactive users
$inactiveUsers = User::active(false)->get();
Conclusions
And that’s it, we have tried our own local scope. Now we know how to create and run a local scope.