Query Builder
The QueryBuilder is the main entry point for building API endpoints. It ties together filtering, sorting, includes, and pagination into a single fluent API.
Basic Usage
use BlueBeetle\ApiToolkit\QueryBuilder;
class ProductController
{
public function index(Request $request)
{
return QueryBuilder::for(Product::class, $request)
->fromResource(ProductResource::class)
->paginate();
}
}
This single call handles:
- Parsing
?filter[name]=widgetand applying allowed filters - Parsing
?sort=-created_at,nameand applying allowed sorts - Parsing
?include=category,tagsand eager loading relationships - Parsing
?page[number]=2&page[size]=20and paginating
From a Resource
The fromResource() method pulls filter, sort, and include configuration from your resource class:
class ProductResource extends Resource
{
public function allowedFilters(): array
{
return [
'name' => new PartialFilter(),
'status' => new ExactFilter(),
'category' => new ScopeFilter(),
];
}
public function allowedSorts(): array
{
return ['name', 'price', 'created_at'];
}
public function defaultSort(): ?string
{
return '-created_at';
}
public function allowedIncludes(): array
{
return ['category', 'tags'];
}
}
Then in your controller, fromResource() picks up all of these automatically.
Overriding Resource Configuration
Method calls take priority over resource definitions:
QueryBuilder::for(Product::class, $request)
->fromResource(ProductResource::class)
->allowedFilters(['name' => new ExactFilter()]) // overrides resource filters
->allowedSorts(['name']) // overrides resource sorts
->defaultSort('name') // overrides resource default
->paginate();
From an Existing Builder
Pass an Eloquent builder instead of a model class to start with a scoped query:
$activeProducts = Product::where('is_active', true);
return QueryBuilder::for($activeProducts, $request)
->fromResource(ProductResource::class)
->paginate();
Pagination Methods
// Offset pagination: ?page[number]=2&page[size]=20
->paginate()
// Cursor pagination: ?page[cursor]=eyJpZCI6MTB9&page[size]=20
->cursorPaginate()
// No pagination, returns all results
->get()
Apply Without Fetching
Use apply() to apply filters, sorts, and includes without executing the query:
$builder = QueryBuilder::for(Product::class, $request)
->fromResource(ProductResource::class)
->apply();
$query = $builder->getQuery(); // Get the underlying Eloquent builder
// Do something custom with the query
$count = $query->count();