Search

Introduction

Laravel Rest Api exposes the search endpoint which is dedicated to access data for your frontend users.

Usage

Here is a quick look at what you can do:

// (POST) api/posts/search
{
  "search": {
    "scopes": [
      {"name": "withTrashed", "parameters": [true]}
    ],
    "filters": [
      {
        "field": "id", "operator": ">", "value": 1, "type": "or"
      },
      {
        "nested": [
          {"field": "user.id", "operator": "<", "value": 2},
          {"field": "id", "operator": ">", "value": 100, "type": "or"}
        ]
      }
    ],
    "sorts": [
      {"field": "user_id", "direction": "desc"},
      {"field": "id", "direction": "asc"}
    ],
    "selects": [
      {"field": "id"}
    ],
    "includes": [
      {
        "relation": "posts",
        "filters": [
          {"field": "id", "operator": "in", "value": [1, 3]}
          ],
        "limit": 2
      },
      {
        "relation": "user",
        "filters": [
          {
            "field": "languages.pivot.boolean",
            "operator": "=",
            "value": true
          }
        ]
      }
    ],
    "aggregates": [
      {
        "relation": "stars",
        "type": "max",
        "field": "rate",
        "filters": [
          {"field": "approved", "value": true}
        ]
      }
    ],
    "instructions": [
      {
        "name": "odd-even-id",
        "fields": [
          { "name": "type", "value": "odd" }
        ]
      }
    ],
    "gates": ["create", "view"],
    "page": 2,
    "limit": 10
  }
}

Specifications

KeyTypeRequiredDefaultDescription
Scopes
scopes.namestringXThe name of the scope
scopes.parametersarrayThe parameters associated with the scope
Filters
filters.fieldstringwhen not nestedThe name of the field
filters.operatorstring=The field operator
filters.valuemixedwhen not nestedThe value you want to filter with
filters.typestringandThe filter condition type
filters.nestedarrayThe nested parameters
Sorts
sorts.fieldstringXThe name of the field
sorts.directionstringascThe direction in which results should be sorted
Selects
selects.fieldstringXThe name of the field
Includes
includes.relationstringXThe relation you are querying
includes.othermixed50You can specify all the arguments in the current page such as filters, limit, scopes, etc except include
Aggregates
aggregates.relationstringXThe relation you are querying
aggregates.typestringXThe type of the aggregates you want to use in: min, max, avg, sum, count and exists
aggregates.fieldstringwhen type is not exists or count*The field you want to execute your aggregate on
aggregates.filtersarrayYou can specify all the arguments for the filters section
Instructions
instructions.namestringXThe instruction uriKey
instructions.fieldsarrayThe fields provided with the instruction. Use instruction listing to see which ones can be provided.
Pagination
pagenumber1The actual page
limitnumber50The maximum number of results
Gates
gatesarrayThe gates you want to get in: create, view, update, delete, restore and forceDelete

Response

As a response you'll receive the filtered records and related metadata:

{
  "current_page": 1,
  "data": [
    {
      "id": 1,
      "name": "Lou West",
      "gates": {
        "authorized_to_view": true,
        "authorized_to_update": true,
        "authorized_to_delete": true,
        "authorized_to_restore": true,
        "authorized_to_force_delete": true
      }
    },
    {
      "id": 2,
      "name": "Bridget Wilderman",
      "gates": {
        "authorized_to_view": true,
        "authorized_to_update": true,
        "authorized_to_delete": true,
        "authorized_to_restore": true,
        "authorized_to_force_delete": true
      }
    }
  ],
  "from": 1,
  "last_page": 1,
  "per_page": 50,
  "to": 2,
  "total": 2,
  "meta": {
    "gates": {
      "authorized_to_create": true
    }
  }
}

Scopes

Scopes corresponds to Laravel's scopes. You'll need to specify them in your resource first to allow their usage.

Use it as the following:

// (POST) api/posts/search
{
  "search": {
    "scopes": [
      {"name": "withTrashed", "parameters": [true]}
    ]
  }
}

Filters

Filters in Laravel Rest Api are the means by which you specify the data you want to retrieve, based on specified fields. All fields specified here must be defined in the fields method of your resource first.

Use it as the following:

// (POST) api/posts/search
{
  "search": {
    "filters": [
      {
        "field": "id", "operator": ">", "value": 1
      }
    ]
  }
}

Field is the column you want to interact with.

Operator must be one of these:

  • =
  • !=
  • >
  • >=
  • <
  • <=
  • like
  • not like
  • in
  • not in

Distant Field

You may specify fields related to relationships by specifying the relationship(s):

// (POST) api/posts/search
{
  "search": {
    "filters": [
      {
        "field": "languages.label",
        "operator": "=",
        "value": "fr"
      }
    ]
  }
}

Type

In many cases you want to condition your multiple filters using an "OR" operation instead of an "AND" one.

You can achieve this by specifying the type of the filter:

// (POST) api/posts/search
{
  "search": {
    "filters": [
      {"field": "user.id", "operator": "<", "value": 2},
      {"field": "id", "operator": ">", "value": 100, "type": "or"}
    ]
  }
}

Here the query will look if the user related id is less than 2 or if the id of the post is greater than 100.

Pivot Filtering

When you deal with a relation that has a pivot such as the BelongsToMany relation, you might want to filter in the pivot table.

You can achieve this by doing:

// (POST) api/posts/search
{
  "search": {
    "filters": [
      {
        "field": "languages.pivot.boolean",
        "operator": "=",
        "value": true
      }
    ]
  }
}

Nested Filtering

You may want to prioritize your condition depending on the filter type because an "AND" operation takes advantage of an "OR" operation.

You can achieve this by doing:

// (POST) api/posts/search
{
  "search": {
    "filters": [
      {
        "field": "id", "operator": "=", "value": 159, "type": "or"
      },
      {
        "field": "name", "operator": "like", "value": "%super post%", "type": "or"
      },
      {
        "nested": [
          {"field": "user.id", "operator": "<", "value": 2},
          {"field": "id", "operator": ">", "value": 100, "type": "or"}
        ]
      }
    ]
  }
}

Here, Laravel Rest Api will look if the id of the posts is 159 OR the name like "%super post%" OR (the user id is less than 2 and the id of the post is greater than 100)

Sorts

Sorts allows you to specify in which order you want to sort your results.

All fields specified here must be defined in the fields method of your resource first.

// (POST) api/posts/search
{
  "search": {
    "sorts": [
      {"field": "user_id", "direction": "desc"},
      {"field": "id", "direction": "asc"}
    ]
  }
}

Selects

In some cases, you may want to specify the columns you want to select because it makes your API faster to not query unnecessary data. By default, Laravel Rest Api will query all your fields. You cannot query columns that are not present in the fields method.

You can achieve this by doing:

// (POST) api/posts/search
{
  "search": {
    "selects": [
      {"field": "id"},
      {"field": "title"}
    ]
  }
}

Includes

In order to limit the number of queries made to the API, Laravel Rest Api allows you to query distant relationships through a single endpoint.

You can achieve this by doing:

// (POST) api/posts/search
{
  "search": {
    "includes": [
      {
        "relation": "posts"
      }
    ]
  }
}

More powerful include

In order to make the include operation much more powerful, Laravel Rest Api allows to specify each argument on this page except include to avoid caveats.

This allows you to do the following:

// (POST) api/posts/search
{
  "search": {
    "includes": [
      {
        "relation": "posts",
        "filters": [
          {"field": "id", "operator": "in", "value": [1, 3]}
        ],
        "limit": 2
      }
    ]
  }
}

Aggregates

If you don't know what an aggregate is, please have a look at the Laravel documentation first.

Laravel Rest Api supports all Laravel's aggregates, here is a quick look at how to specify your aggregate:

// (POST) api/posts/search
{
  "search": {
    "aggregates": [
      {
        "relation": "comments",
        "type": "avg",
        "field": "stars"
      }
    ]
  }
}

Here we are getting the average stars for the comments linked to the posts.

The type could be one of these:

  • min
  • max
  • avg
  • sum
  • count
  • exists
  For the exists and count operation you must not specify the field since these aggregates don't base themselves on a column.

Aggregates filtering

For more complex aggregates, Laravel Rest Api allows you to specify filters. These filters are the same as the basic ones.

// (POST) api/posts/search
{
  "search": {
    "aggregates": [
      {
        "relation": "comments",
        "type": "avg",
        "field": "stars",
        "filters": [
          {"field": "approved", "value": true}
        ]
      }
    ]
  }
}

Instructions

Instructions is a way for api builder to define strong query operations. They'll be defined in the resource details when exposed.

Here is how to specify an instruction:

// (POST) api/posts/search
{
  "search": {
    "instructions": [
      {
        "name": "odd-even-id"
      }
    ]
  }
}

Here we are getting the posts that have an even id.

The specified name is the uriKey of the instruction.

Instructions fields

For more complex instructions, Laravel Rest Api allows you to specify fields. You can have full access to the fields and validation in the resource details.

// (POST) api/posts/search
{
  "search": {
    "instructions": [
      {
        "name": "odd-even-id",
        "fields": [
          {"field": "type", "value": "odd"}
        ]
      }
    ]
  }
}

Pagination

You might either want to limit the data you are querying or to specify a page to load data by sequence. All limits specified here must be defined in the limits method of your resource first.

You can achieve this by doing:

// (POST) api/posts/search
{
  "search": {
    "page": 2,
    "limit": 10
  }
}

Gates

If you want to retrieve permissions on the models you are getting, you need to specify the gates you want to get. Use this with care this can slow down you application queries.

Be aware before that Gates needs to be enabled in order to be retrieved. Have a look at Automatic Gates if you need detail.

The gates could be one of these:

  • create
  • view
  • update
  • delete
  • restore
  • forceDelete
// (POST) api/posts/search
{
  "search": {
    "gates": ["create", "view"]
  }
}