Eloquent Query Constraints with Scope in Laravel

At times in the course of a laravel project, it’s necessary to run a certain query more than once. For instance, in a blog project, it is necessary to get all active posts and this can be done like this.

Post::where('active', true)->get();

You could do this wherever you need to get active posts. But to ensure DRY (Don’t Repeat Yourself), you can abstract your logic into your model using scopes. To define a scope, you define a method on the model that starts with scope eg.

// /App/Post
public function scopeActive($query){
return $query->where('active', true);
}

The function takes the eloquent query builder as parameter and returns a query builder. To use a scope, you access it like other query builder methods but without the scope in the name.

Post::active()->get();
OR
Post::active()->paginate(30);
OR
Post::active()->latest()->paginate(30);

Oh! latest() is the short cut to ordering by created_at in descending order. i.e.

Post::active()->orderBy('created_at', 'desc')->paginate();
//The opposite is oldest() i.e.
Post::active()->oldest()->paginate();

You can also create dynamic scopes. This gives you the ability to pass parameters to your scopes. For example, the scope above could be modified to get either active or non active posts only. Example.

// /App/Post
public function scopeActive($query, $active){
return $query->where('active', $active);
}

To use this, you can do the following.

Post::active(true)->get(); //For active posts
Post::active(false)->get(); For non active posts

Scopes could be as complex or as simple as intended. It also helps you clean up your controllers i.e. abstracting complex queries into scopes.

That’s all.