spatie/laravel-query-builder
Safely build Eloquent queries from incoming API requests. Allowlist filters, sorts, includes, and fields; supports partial/exact and custom filters, nested relationships, relation counts, and default values. Works with existing queries for clean, consistent endpoints.
Pros:
allowedFilters, allowedSorts) to enforce security and performance boundaries (e.g., preventing SQL injection or unintended data exposure).QueryBuilder::for($existingQuery)), enabling incremental adoption in legacy systems.beginsWith/endsWith filters and field selection reduce payload size and improve query efficiency.Cons:
filter[] parameters) can make static analysis or caching harder without explicit opt-ins (e.g., caching strategies for filtered queries).LIKE vs. = queries) may vary.allowedFilters), but misconfiguration (e.g., allowing raw SQL input) could introduce risks.fields[]) must be explicitly configured to avoid leaking sensitive columns.include[] prevents N+1 issues but requires explicit relationship definitions.allowed* methods and query profiling.QueryBuilder with manual queries).allowedFilters/allowedSorts be configured? Will roles/permissions dynamically restrict these (e.g., admin vs. public API)?LIKE filters) be detected and addressed? Integrate with Laravel Debugbar or query logging.QueryBuilder’s caching features (if extended) for filtered/sorted results.QueryBuilder adoption with reduced boilerplate and consistency.spatie/laravel-query-builder for GraphQL resolvers (though this package is REST-focused).public function index(Request $request) {
return User::where('active', true)
->when($request->has('name'), fn($q) => $q->where('name', 'like', '%'.$request->name.'%'))
->get();
}
with:
public function index() {
return QueryBuilder::for(User::class)
->allowedFilters('name')
->allowedFilters(AllowedFilter::exact('active'))
->get();
}
QueryBuilder usage.// Before: Scattered in controllers
User::whereHas('posts', fn($q) => $q->where('published', true));
// After: Centralized in QueryBuilder
QueryBuilder::for(User::class)
->allowedFilters(AllowedFilter::belongsTo('posts', 'published_posts'))
->get();
QueryBuilder once all endpoints are migrated.LIKE vs. ILIKE in PostgreSQL).QueryBuilder usage or add default configurations.QueryBuilder facade in tests to mock dynamic queries.composer require spatie/laravel-query-builder.php artisan vendor:publish --provider="Spatie\QueryBuilder\QueryBuilderServiceProvider".config/query-builder.php (e.g., disable exceptions for invalid filters).QueryBuilder in controllers.LIKE on large tables).allowedFilters to use exact matches where possible.How can I help you explore Laravel packages today?