Query Builder
QueryBuilder extends TableBuilder and is returned automatically when you pass an Eloquent query builder or relation
to TableBuilder::for(). It handles all database operations: filtering, searching, sorting, and pagination.
How It Is Created
// These all return a QueryBuilder instance:
TableBuilder::for(User::query())
TableBuilder::for(User::class)
TableBuilder::for($user->orders())
TableBuilder::for(new User)
Pagination Methods
Must call one of these to execute the query:
->paginate(15) // LengthAwarePaginator - shows total count
->simplePaginate(15) // SimplePaginator - Previous/Next only
->cursorPaginate(15) // CursorPaginator - efficient for huge tables
->noPagination() // Fetch all results with get()
Omitting perPage uses default_per_page from the config (25 out of the box). A ?perPage= value from the query
string wins, but only when it is one of the configured perPageOptions.
Case Sensitivity
->ignoreCase(true) // case-insensitive search (default)
->ignoreCase(false) // case-sensitive search
- MySQL: toggles between
LIKEandLIKE BINARY - PostgreSQL: toggles between
ILIKEandLIKE
Term Parsing
By default, search terms are split on spaces and combined with OR: john doe returns rows matching john OR doe.
Quoted phrases in the input are kept together.
->parseTerms(true) // split on spaces (default)
->parseTerms(false) // treat entire input as one term
Eager Loading
Columns using dot notation for relationships are eager-loaded automatically:
->column('company.name', 'Company')
// Adds: $query->with('company')
Filter Application Order
When loadResource() is called:
- Callback/select filters applied (
applyFilters) - Search inputs applied (
applySearchInputs) - Sorting + eager loading applied (
applySortingAndEagerLoading) - Default sort applied if no sort query param
- Pagination executed
Query builder resources are filtered by the query only, paginated or not. The in-memory collection filter applies to
array and Collection resources. See Search.
Spatie QueryBuilder Support
You can pass a Spatie QueryBuilder instance. In that case the package skips its own filter/search/sort application and lets Spatie handle those, but still manages pagination and the Vue frontend:
use Spatie\QueryBuilder\QueryBuilder as SpatieQueryBuilder;
$query = SpatieQueryBuilder::for(User::class)
->allowedFilters(['name', 'email'])
->allowedSorts(['name', 'created_at']);
TableBuilder::for($query)->paginate(15);
Bulk Action Processing
When a bulk action targets "all results", the query re-applies all active filters and search inputs before chunking:
->bulkAction('Export', each: fn($user) => $user->export())
Rows are processed in chunks of 1,000 via chunkById to handle large datasets safely.
Conditionable
QueryBuilder (like TableBuilder) uses Laravel's Conditionable trait, so you can use when() and unless():
TableBuilder::for(User::query())
->when($request->user()->isAdmin(), fn($table) => $table->column('secret_field', 'Secret'))
->column('name', 'Name')
->paginate(15);
