Kritim Yantra
Apr 16, 2025
In this blog post, we'll explore how to use the Spatie Laravel-Query-Builder package in Laravel 12 to create powerful, filterable API endpoints with minimal code. This package simplifies complex query building while maintaining clean, readable syntax.
The Spatie Laravel-Query-Builder package provides an elegant way to:
?filter[name]=John
).?sort=name,-created_at
).?include=posts,comments
).?fields[users]=id,name
).It's perfect for building RESTful APIs with complex filtering requirements.
If you don’t have Laravel 12 installed:
composer create-project laravel/laravel query-builder-demo
cd query-builder-demo
composer require spatie/laravel-query-builder
php artisan make:model Post -mcr
Run migrations:
php artisan migrate
In your controller (PostController.php
):
use Spatie\QueryBuilder\QueryBuilder;
public function index()
{
$posts = QueryBuilder::for(Post::class)
->allowedFilters(['title', 'author'])
->get();
return response()->json($posts);
}
Now you can filter via URL:
/posts?filter[title]=Laravel&filter[author]=John
By default, filters use exact matching. For partial matches:
->allowedFilters(['title', AllowedFilter::partial('author')])
Now ?filter[author]=jo
matches "John".
use Spatie\QueryBuilder\AllowedFilter;
->allowedFilters([
AllowedFilter::callback('published_after', function ($query, $value) {
$query->where('published_at', '>=', $value);
})
])
Usage:
/posts?filter[published_after]=2024-01-01
Apply model scopes directly:
->allowedFilters([
AllowedFilter::scope('popular'),
])
In Post.php
:
public function scopePopular($query)
{
return $query->where('views', '>', 1000);
}
Usage:
/posts?filter[popular]=true
->allowedSorts(['title', 'created_at'])
Usage:
/posts?sort=title,-created_at // (Descending)
->allowedSorts([
AllowedSort::custom('length', new StringLengthSort()),
])
See official docs for custom sort classes.
->allowedIncludes(['author', 'comments'])
Usage:
/posts?include=author,comments
->allowedIncludes(['author.profile'])
Now ?include=author.profile
works.
$posts = QueryBuilder::for(Post::class)
->paginate();
URL:
/posts?page=2
->paginate(perPage: 15)
Or via request:
/posts?page=2&per_page=15
->allowedFields(['id', 'title'])
Usage:
/posts?fields[posts]=id,title
/posts?include=author&fields[author]=name
QueryBuilder::for(Post::class)
->defaultFilter('status', 'published')
return PostResource::collection($query->paginate());
allowedFilters()
carefully to avoid slow queries.The Spatie Laravel-Query-Builder package supercharges Laravel APIs by:
✅ Simplifying complex filtering with URL parameters.
✅ Reducing boilerplate code for sorting & relationships.
✅ Maintaining clean, readable syntax.
✅ Working seamlessly with pagination & resources.
Perfect for admin panels, public APIs, or data-heavy applications.
Happy query building! 🚀
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 12, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google