The biggest change in v4 is the way requested filters, includes and fields are processed. In previous versions we would automatically camel-case relationship names for includes and nested filters. Requested (nested) fields would also be transformed to their plural snake-case form, regardless of what was actually requested.
In v4 we've removed this behaviour and will instead always pass the requested filter, include or field from the request URL to the query.
When following Laravel's convention of camelcase relationship names, a request will look like this:
GET /api/users
?includes=latestPosts,friendRequests
&filters[homeAddress.city]=Antwerp
&fields[related_models.test_models]=id,name
The a minimal QueryBuilder
for the above request looks like this:
use Spatie\QueryBuilder\QueryBuilder;
QueryBuilder::for(User::class)
->allowedIncludes(['latestPosts', 'friendRequests'])
->allowedFilters(['homeAddress.city'])
->allowedFields(['related_models.test_models.id', 'related_models.test_models.name']);
There is no automated upgrade path available at this time.
Possible changes in this version due to internal changes.
The package's Spatie\QueryBuilder\QueryBuilder
class no longer extends Laravel's Illuminate\Database\Eloquent\Builder
. This means you can no longer pass a QueryBuilder
instance where a Illuminate\Database\Eloquent\Builder
instance is expected. However, all Eloquent method calls get forwarded to the internal Illuminate\Database\Eloquent\Builder
.
Using $queryBuilder->getEloquentBuilder()
you can access the internal Illuminate\Database\Eloquent\Builder
.
There are a lot of renamed methods and classes in this release. An advanced IDE like PhpStorm is recommended to rename these methods and classes in your code base. Use the refactor -> rename functionality instead of find & replace.
- rename
Spatie\QueryBuilder\Sort
toSpatie\QueryBuilder\AllowedSort
- rename
Spatie\QueryBuilder\Included
toSpatie\QueryBuilder\AllowedInclude
- rename
Spatie\QueryBuilder\Filter
toSpatie\QueryBuilder\AllowedFilter
- replace request macro's like
request()->filters()
,request()->includes()
, etc... with their related methods on theQueryBuilderRequest
class. This class needs to be instantiated with a request object, (more info here: #328):request()->includes()
->QueryBuilderRequest::fromRequest($request)->includes()
request()->filters()
->QueryBuilderRequest::fromRequest($request)->filters()
request()->sorts()
->QueryBuilderRequest::fromRequest($request)->sorts()
request()->fields()
->QueryBuilderRequest::fromRequest($request)->fields()
request()->appends()
->QueryBuilderRequest::fromRequest($request)->appends()
- please note that the above methods on
QueryBuilderRequest
do not take any arguments. You can use thecontains
to check for a certain filter/include/sort/... - make sure the second argument for
AllowedSort::custom()
is an instance of a sort class, not a classnameAllowedSort::custom('name', MySort::class)
->AllowedSort::custom('name', new MySort())
- make sure the second argument for
AllowedFilter::custom()
is an instance of a filter class, not a classnameAllowedFilter::custom('name', MyFilter::class)
->AllowedFilter::custom('name', new MyFilter())
- make sure all required sorts are allowed using
allowedSorts()
- make sure all required field selects are allowed using
allowedFields()
- make sure
allowedFields()
is always called beforeallowedIncludes()