Spatie Parity Matrix
Every laravel-query-builder v7 feature, the URL it emits, the matching crisp-oquent builder method.
Filtering
| Spatie feature | URL | Builder | Spatie version |
|---|---|---|---|
| Partial filter | ?filter[name]=john | .filter('name', 'john') | 1.0+ |
| Exact filter | ?filter[id]=1 | .filter('id', 1) | 1.0+ |
| Comma-separated values | ?filter[id]=1,2,3 | .filter('id', [1,2,3]) | 1.0+ |
Operator (DYNAMIC) | ?filter[salary]=>3000 | .where('salary', FilterOperator.GREATER_THAN, 3000) | 6.0+ |
| BelongsTo | ?filter[post]=1 | .filter('post', 1) | 5.x+ |
| Trashed (SoftDeletes) | ?filter[trashed]=with | .withTrashed() | 1.0+ |
| Trashed only | ?filter[trashed]=only | .onlyTrashed() | 1.0+ |
| Nullable | ?filter[deleted_at]=null | .whereNull('deleted_at') | 7.0.1 |
| Nullable not | ?filter[email]=not-null | .whereNotNull('email') | 7.0.1 |
| Custom array delimiter | ?filter[id]=1|2|3 | .delimiter('|') / setFilterDelimiter('|') | 7.2.0 |
| Filter Group (OR) | ?filter[q]=John | .filterGroup('q', 'John') | 7.3.0 |
| Filter Group (AND) | ?filter[strict]=val | .filterGroup('strict', 'val') | 7.3.0 |
| Scope filter | ?filter[starts_before]=2026-12-31 | .filter('starts_before', '2026-12-31') | 1.0+ |
| Custom callback filter | ?filter[xyz]=... | .filter('xyz', value) | 1.0+ |
Sorting
| Feature | URL | Builder |
|---|---|---|
| Asc sort | ?sort=name | .sortBy('name') |
| Desc sort | ?sort=-created_at | .sortByDesc('created_at') |
| Multi-field | ?sort=-created_at,name | .sortByDesc('created_at').sortBy('name') |
| Custom sort alias | ?sort=name-length | .sortBy('name-length') (server: AllowedSort::custom) |
| Sort by aliased column | ?sort=-street | .sortByDesc('street') (server: AllowedSort::field) |
Including relations
| Feature | URL | Builder | Spatie version |
|---|---|---|---|
| Relation | ?include=posts | .include('posts') | 1.0+ |
| Multiple | ?include=posts,permissions | .include('posts', 'permissions') | 1.0+ |
| Nested | ?include=posts.comments | .include('posts.comments') | 1.0+ |
| Count aggregate | ?include=postsCount | .includeCount('posts') | 4.x+ |
| Exists aggregate | ?include=postsExists | .includeExists('posts') | 5.x+ |
| Sum aggregate | ?include=postsViewsSum | .includeSum('postsViewsSum') | 7.0.0 |
| Avg aggregate | ?include=postsViewsAvg | .includeAvg('postsViewsAvg') | 7.0.0 |
| Min aggregate | ?include=postsViewsMin | .includeMin('postsViewsMin') | 7.0.0 |
| Max aggregate | ?include=postsViewsMax | .includeMax('postsViewsMax') | 7.0.0 |
| Include alias | ?include=profile | .include('profile') (server: AllowedInclude::relationship) | 4.x+ |
| Custom include | ?include=... | .include(name) (server: AllowedInclude::custom) | 1.0+ |
Sparse fieldsets
| Feature | URL | Builder |
|---|---|---|
| Per-resource fields | ?fields[users]=id,name | .fields('users', 'id', 'name') |
| Fields on included | ?fields[authors]=id,name | .fields('authors', 'id', 'name') |
Append accessors
| Feature | URL | Builder |
|---|---|---|
| Append accessor | ?append=full_name | .append('full_name') |
| Multiple | ?append=full_name,avatar_url | .append('full_name', 'avatar_url') |
Pagination
| Feature | URL | Builder |
|---|---|---|
| Page + size | ?page=2&per_page=25 | .paginate(2, 25) |
| Single page | ?page=1&per_page=15 | .paginate() (defaults) |
| All pages | n/a | .all() (walks until exhausted) |
What's not in crisp-oquent (yet)
- Full JSON:API Fancy Filters URL syntax (
?filter[g1][conjunction]=OR&filter[g1][conditions][...]) — listed as a follow-up in Spatie #1060. When the upstream PR lands, the corresponding builder DSL will follow. groupNot/ nested groups — also out-of-scope of #1060, planned for a follow-up.