I'm always excited to take on new projects and collaborate with innovative minds.
Laravel’s Eloquent ORM is a powerful tool for interacting with databases. It simplifies complex query operations and brings joy to developers by providing a clean, elegant syntax. One of its underrated features is query scopes, which allow you to encapsulate commonly used query logic within your model.
In this post, we’ll explore how to create and use custom query scopes in Laravel to make your code more reusable, readable, and maintainable. By the end, you’ll wonder how you ever lived without them! 🛠️
Query scopes are methods on your Eloquent models that allow you to define reusable query logic. They help streamline your database interactions, especially when you find yourself writing the same query logic in multiple places.
Laravel offers two types of scopes:
In this guide, we’ll focus on local scopes, which are simple yet powerful tools for improving your codebase.
Here are some reasons to adopt query scopes:
Let’s dive into a practical & very simple example! 🌊
Imagine you have a blogging application with a Post
model. You frequently need to fetch posts marked as "published" from your database. Instead of repeating this query logic, you can create a custom query scope.
To start, add a scope method to your Post
model. Laravel uses the scope
prefix for query scopes.
Here’s how you define a published
scope:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
/**
* Scope a query to only include published posts.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePublished($query)
{
return $query->where('is_published', true);
}
}
📢Pro Tip: The scope prefix is only used when defining the method. You’ll call it without the scope prefix.
Now, let’s see how this scope simplifies your queries. In your PostController
, you can retrieve only published posts with a single method call:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
class PostController extends Controller
{
public function index()
{
// Fetch all published posts
$publishedPosts = Post::published()->get();
return view('posts.index', ['posts' => $publishedPosts]);
}
}
Notice how clean and descriptive the query becomes! Instead of repeating the where
clause every time, you simply chain the published
method.
You can also test your scope directly in Laravel Tinker or within your routes:
php artisan tinker
>>> App\Models\Post::published()->get();
Using in Routes:
Route::get('/published-posts', function () {
return App\Models\Post::published()->get();
})
Scopes are flexible and can accept parameters. Let’s extend our Post
model with another scope to filter posts by a specific author:
public function scopeByAuthor($query, $authorId)
{
return $query->where('author_id', $authorId);
}
Now you can chain scopes for even more concise and readable queries:
$posts = Post::published()->byAuthor(1)->get();
Here’s a summary of why query scopes are a game-changer:
Post::published()
clearly convey intent.While this article focuses on local scopes, it’s worth mentioning global scopes. These automatically apply to all queries for a model. For example, you might want to always exclude soft-deleted records from queries.
Here’s a quick example of defining a global scope:
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class PublishedScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('is_published', true);
}
}
// Applying the global scope
Post::addGlobalScope(new PublishedScope);
Global scopes can be powerful but should be used sparingly, as they affect every query on the model.
Custom query scopes are an excellent way to keep your Laravel application clean, readable, and maintainable. Whether you’re building a blog, an e-commerce site, or a SaaS product, query scopes help encapsulate common query logic and make your code more expressive.
Next time you find yourself repeating a query in multiple places, take a step back and consider creating a scope. Your future self (and your team) will thank you! 🙌
Happy coding! 😄
Your email address will not be published. Required fields are marked *