Basic usage
The spatie-compatible API is the QueryBuilder class. It wraps an Eloquent query and applies the request parameters you allow:
use App\Models\User;
use MyProgs\QueryBuilder\AllowedFilter;
use MyProgs\QueryBuilder\AllowedSort;
use MyProgs\QueryBuilder\QueryBuilder;
class UserController
{
public function index()
{
return QueryBuilder::for(User::class)
->allowedFields('id', 'name', 'email', 'posts.id', 'posts.title')
->allowedIncludes('posts', 'posts.comments')
->allowedFilters('name', AllowedFilter::exact('id'), AllowedFilter::scope('active'))
->allowedSorts('name', AllowedSort::field('created', 'created_at'))
->defaultSort('-created')
->paginate();
}
}GET /users?fields[users]=id,name&fields[posts]=title&include=posts&filter[name]=john&sort=-createdThe request selects users.id and users.name for the users and posts.title for their posts. Because posts is included, posts.user_id is added to the posts query, so every user comes back with its posts loaded.
The subject
QueryBuilder::for() takes:
- a model class:
QueryBuilder::for(User::class); - an Eloquent builder:
QueryBuilder::for(User::where('active', true)); - a relation:
QueryBuilder::for($team->users()).
The request is taken from the container. Pass another one as the second argument: QueryBuilder::for(User::class, $request).
Using the result
QueryBuilder forwards every other method to the Eloquent builder, so you can chain where(), with(), scopes, and finish with get(), first(), paginate(), simplePaginate(), cursorPaginate() and the like:
$users = QueryBuilder::for(User::class)
->allowedFilters('name')
->where('active', true)
->get();Filters and sorts are applied when you call allowedFilters() and allowedSorts(). Fields and includes are applied right before the first call that reads the query. See Differences from spatie.
getEloquentBuilder()returns the Eloquent builder with everything applied.getSubject()returns the builder or relation as it was given, without the pending fields and includes.clone()returns an independent copy, asclone $querydoes.
Errors
A parameter that is not allowed throws an exception that renders as a 400 response:
| Exception | When |
|---|---|
InvalidFilterQuery | an unknown filter |
InvalidSortQuery | an unknown sort |
InvalidIncludeQuery | an unknown include |
InvalidFieldQuery | an unknown field |
MalformedQueryParameter | an array where a string is expected |
All of them extend MyProgs\QueryBuilder\Exceptions\InvalidQuery, an HttpException. Unknown filters, sorts and includes can be ignored instead, see Configuration.
Reading the request
QueryBuilderRequest gives the parsed parameters as collections, for code that needs them outside a query:
use MyProgs\QueryBuilder\QueryBuilderRequest;
$request = QueryBuilderRequest::fromRequest(request());
$request->filters(); // ['name' => 'john']
$request->sorts(); // ['-created']
$request->includes(); // ['posts']
$request->fields(); // ['users' => ['id', 'name'], 'posts' => ['title']]The names and the delimiter come from the query-builder config.