Filtering

For the get command you can filter by using the following url patterns

Seperator Description Example Result
= Equals ?filter[field]=hello select ... where field = 'hello'
!= Not Equals ?filter[field!]=hello select ... where field != 'hello'
<> Not Equals (alt) ?filter[field<>]=hello select ... where field != 'hello'
> Greater Than ?filter[field>]=5 select ... where field > 5
>= Greater Or Equal to ?filter[field>=]=5 select ... where field >= 5
< Less Than ?filter[field<]=5 select ... where field <> 5
<= Less Or Equal to ?filter[field<=]=5 select ... where field <= 5
~ Contains (LIKE with wildcard on both sides) ?filter[field~]=hello select ... where field like '%hello%'
^ Starts with (LIKE with wildcard on end) ?filter[field^]=hello select ... where field like 'hello%'
$ Ends with (LIKE with wildcard on start) ?filter[field$]=hello select ... where field like 'hello%'
!~ Not Contains (LIKE with wildcard on both sides) ?filter[field!~]=hello select ... where field not like '%hello%'
!^ Not Starts with (LIKE with wildcard on end) ?filter[field!^]=hello select ... where field not like 'hello%'
!$ Not Ends with (LIKE with wildcard on start) ?filter[field!$]=hello select ... where field not like 'hello%'

In / Not In

You can pass to the filters an array of values ie: filter[user_id]=1||2||||4||7 or filter[user_id!]=55||33

Null / Not Null (introduced 1.23.0)

If you need to filter on whether a field is null or not null, you can use the filter param as of version 1.23.0 EG: filter[age]=NULL or filter[age!]=NULL. Note that NULL must be uppercase.

Older versions Add a scope to your model: eg


public function scopeAgeNull(Builder $builder, $isNull = true){
  $isNull ? $builder->whereNull('age') : $builder->whereNotNull('age');
}

Add to your allowedScopes and can then be called in url as ?ageNull=1 for where null and ?ageNull=0 for where age not null

Scopes

In addition to filtering, you can use Laravel's Eloquent Query Scopes to do more complex searches or filters. Simply add an $allowedScopes to your ApiResource, and that scope will be exposed as a query parameter.

Assuming you have a scopeFullname defined on your Eloquent Model, you can expose this scope to your API as follows:

protected static $allowedScopes = [
  'fullname'
];

Given the above $allowedScopes array, your API consumers will now be able to request ?fullname=John. The query parameter value will be passed to your scope function in your Eloquent Model.

Filtering on related models

You can easily filter using any related model that is configured for include. Simply specify ?filter[model.field]=123 in your query string. The same filter options above apply to related fields.


Fields, Relationships, Sorting & Pagination

Fields

By default all fields are returned, you can limit that to specific fields in the following ways:

  • Api Controller parameter $defaultFields default as protected $defaultFields = ['*']; - switch to include an array of fields
  • fields param in url querystring: ie fields=id,name,age = will only return those, this will also override the above.
  • in your response resource you can set the static::allowedFields to lock down which fields are returnable
  • addfields and removefields params in url querystring will work with these.
  • Use laravel eloquent model $appends property to automatically include custom attribute accessors.

Relationships

  • Using the relationships defined in your models, you can pass a comma delimited list eg include=join1,join2 which will return those joins (one or many).

Simply add a protected static $mapResources to your Resource to define which resources to assign your related data. E.e., for a one to many relationship, you should specify a collection, and a one-to-one relationship specify the related resource directly. This will allow the API to properly format the related record.

    protected static $mapResources = [
        'notes' => NotesCollection::class,
        'owner' => OwnerResource::class
    ];
  • You can automatically update and create related records for most types of relationships. Just include the related resource name in your POST or PUT request.

For BelongsToMany or MorphToMany relationships, you can choose the sync strategy. By default, this will take an additive strategy. That is to say, related records sent will be ADDED to any existing related records. On a request-by-request basis, you can opt for a sync strategy which will remove the pivot for any related records not listed in the request. Note the actual related record will not be removed, just the pivot entry.

To opt for the sync behavaiour, set ?sync[field]=true in your request.

Sorting

  • Sorts can be passed as comma list aswell, ie sort=age asc or sort=age asc,name desc,eyes - generates sql of sort age asc and sort age asc, name desc, eyes asc respectively
  • Default sort can also be added on the controller using by overrideing the protected $defaultSort = null; parameter

Pagination

  • pagination can be enabled/disbled on the controller by overriding the protected $defaultLimit = 25; on the controller
  • pagination can also be passed via the url using limit=xx&page=y
  • pagination can also be limited to a max per page by overriding the protected $maximumLimit = false; parameter

Validation

  • When Posting a new record, validation can be done by adding a rulesForCreate method to your controller returning an array eg
[
    'email' => ['required', 'email'],
    'games' => 'required|numeric',
]

A better solution would be to use the Form Request Validation