PHPackages                             barisbora/laravel-query-builder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. barisbora/laravel-query-builder

AbandonedArchivedLibrary[API Development](/categories/api)

barisbora/laravel-query-builder
===============================

Easily build Eloquent queries from API requests

v1.4(7y ago)41.3k3[1 PRs](https://github.com/barisbora/laravel-query-builder/pulls)MITPHPPHP ^7.1

Since Jul 14Pushed 7y ago1 watchersCompare

[ Source](https://github.com/barisbora/laravel-query-builder)[ Packagist](https://packagist.org/packages/barisbora/laravel-query-builder)[ Docs](https://github.com/barisbora/laravel-query-builder)[ RSS](/packages/barisbora-laravel-query-builder/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (5)Dependencies (2)Versions (6)Used By (0)

Easily build Eloquent queries from API requests
===============================================

[](#easily-build-eloquent-queries-from-api-requests)

[![Latest Version on Packagist](https://camo.githubusercontent.com/4e0d6643bad272dbce941b7a77c1bb874065ea3537828d2126d1f076dd654488/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6c61726176656c2d71756572792d6275696c6465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-query-builder)[![Build Status](https://camo.githubusercontent.com/a6b1b95ab7f0266b84edb74d3369e7a2d2dea31dc1c1c4f6dae1e280b4962a91/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f7370617469652f6c61726176656c2d71756572792d6275696c6465722f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/spatie/laravel-query-builder)[![StyleCI](https://camo.githubusercontent.com/a05ffc060ed2ec30da78c30c6ca0326a3bdd4337c0ccafaffafe3a504ffcba17/68747470733a2f2f7374796c6563692e696f2f7265706f732f3131373536373333342f736869656c643f6272616e63683d6d6173746572)](https://styleci.io/repos/117567334)[![Quality Score](https://camo.githubusercontent.com/0b6c33ebc7f946bed571954536eda824a179dee7d216677f803d69b1180fdbae/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f7370617469652f6c61726176656c2d71756572792d6275696c6465722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/spatie/laravel-query-builder)[![Total Downloads](https://camo.githubusercontent.com/b06894bff55703ad61b99a25a3d21a081bce61e0bfee82d517a8c73073031d3e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6c61726176656c2d71756572792d6275696c6465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-query-builder)

This package allows you to filter, sort and include eloquent relations based on a request. The `QueryBuilder` used in this package extends Laravel's default Eloquent builder. This means all your favorite methods and macros are still available. Query parameter names follow the [JSON API specification](http://jsonapi.org/) as closely as possible.

Basic usage
-----------

[](#basic-usage)

Filtering an API request: `/users?filter[name]=John`:

```
use Spatie\QueryBuilder\QueryBuilder;

// ...

$users = QueryBuilder::for(User::class)
    ->allowedFilters('name')
    ->get();
// all `User`s that contain the string "John" in their name
```

Requesting relations from an API request: `/users?include=posts`:

```
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts')
    ->get();
// all `User`s with their `posts` loaded
```

Works together nicely with existing queries:

```
$query = User::where('active', true);

$user = QueryBuilder::for($query)
    ->allowedIncludes('posts', 'permissions')
    ->where('score', '>', 42) // chain on any of Laravel's query builder methods
    ->first();
```

Sorting an API request: `/users?sort=name`:

```
$users = QueryBuilder::for(User::class)->get();
// all `User`s sorted by name
```

Have a look at the [usage section](#usage) below for advanced examples and features.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require spatie/laravel-query-builder
```

You can optionally publish the config file with:

```
php artisan vendor:publish --provider="Spatie\QueryBuilder\QueryBuilderServiceProvider" --tag="config"
```

This is the contents of the published config file:

```
return [

    /*
     * By default the package will use the `include`, `filter`, `sort` and `fields` query parameters.
     *
     * Here you can customize those names.
     */
    'parameters' => [
        'include' => 'include',

        'filter' => 'filter',

        'sort' => 'sort',

        'fields' => 'fields',
    ],

];
```

Usage
-----

[](#usage)

### Including relationships

[](#including-relationships)

The `include` query parameter will load any Eloquent relation on the results collection. By default, no includes are allowed. All includes must be specified using `allowedIncludes()`.

```
// GET /users?include=posts
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts')
    ->get();

// $users will contain all users with their posts loaded
```

You can load multiple relationship by separating them with a comma:

```
// GET /users?include=posts,permissions
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts', 'permissions')
    ->get();

// $users will contain all users with their posts and permissions loaded
```

You can also pass in an array of includes to the `allowedIncludes()` method.

```
// GET /users?include=posts,permissions
$users = QueryBuilder::for(User::class)
    ->allowedIncludes(['posts', 'permissions'])
    ->get();

// $users will contain all users with their posts and permissions loaded
```

You can load nested relationships using `.`:

```
// GET /users?include=posts.comments,permissions
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts.comments', 'permissions')
    ->get();

// $users will contain all users with their posts, comments on their posts and permissions loaded
```

When trying to include relationships that have not been allowed using `allowedIncludes()` an `InvalidIncludeQuery` exception will be thrown.

Relation/include names will be converted to camelCase when looking for the corresponding relationship on the model. This means `/users?include=blog-posts` will try to load the `blogPosts()` relationship on the `User` model.

Once the relationships are loaded on the results collection you can include them in your response by using [Eloquent API resources and conditional relationships](https://laravel.com/docs/5.5/eloquent-resources#conditional-relationships).

### Filtering

[](#filtering)

The `filter` query parameters can be used to filter results by partial property value, exact property value or if a property value exists in a given array of values. You can also specify custom filters for more advanced queries.

By default, no filters are allowed. All filters have to be specified using `allowedFilters()`. When trying to filter on properties that have not been allowed using `allowedFilters()` an `InvalidFilterQuery` exception will be thrown.

```
// GET /users?filter[name]=john&filter[email]=gmail
$users = QueryBuilder::for(User::class)
    ->allowedFilters('name', 'email')
    ->get();
// $users will contain all users with "john" in their name AND "gmail" in their email address
```

You can also pass in an array of filters to the `allowedFilters()` method.

```
// GET /users?filter[name]=john&filter[email]=gmail
$users = QueryBuilder::for(User::class)
    ->allowedFilters(['name', 'email'])
    ->get();
// $users will contain all users with "john" in their name AND "gmail" in their email address
```

You can specify multiple matching filter values by passing a comma separated list of values:

```
// GET /users?filter[name]=seb,freek
$users = QueryBuilder::for(User::class)
    ->allowedFilters('name')
    ->get();
// $users will contain all users that contain "seb" OR "freek" in their name
```

#### Exact filters

[](#exact-filters)

When filtering models based on their IDs, a boolean value or a literal string, you'll want to use exact filters. This way `/users?filter[id]=1` won't match all users containing the digit `1` in their ID.

Exact filters can be added using `Spatie\QueryBuilder\Filter::exact('property_name')` in the `allowedFilters()` method.

```
use Spatie\QueryBuilder\Filter;

// GET /users?filter[name]=John%20Doe
$users = QueryBuilder::for(User::class)
    ->allowedFilters(Filter::exact('name'))
    ->get();
// all users with the exact name "John Doe"
```

The query builder will automatically map `'true'` and `'false'` as booleans and a comma separated list of values as an array:

```
use Spatie\QueryBuilder\Filter;

// GET /users?filter[id]=1,2,3,4,5&filter[admin]=true
$users = QueryBuilder::for(User::class)
    ->allowedFilters(Filter::exact('id'), Filter::exact('admin'))
    ->get();
// $users will contain all admin users with id 1, 2, 3, 4 or 5
```

#### Scope filters

[](#scope-filters)

Sometimes you'll want to build more advanced filtering queries. This is where scope filters and custom filters come in handy.

Scope filters allow you to easily add [local scopes](https://laravel.com/docs/5.6/eloquent#local-scopes) to your query by adding filters to the URL.

Consider the following scope on your model:

```
public function scopeStartsBefore(Builder $query, $date): Builder
{
    return $query->where('starts_at', '>=', Carbon::parse($date));
}
```

To filter based on the `startsBefore` scope simply add it to the `allowedFilters` on the query builder:

```
QueryBuilder::for(Event::class)
    ->allowedFilters([
        Filter::scope('starts_before'),
    ])
    ->get();
```

The following filter will now add the `startsBefore` scope to the underlying query:

```
GET /events?filter[starts_before]=2018-01-01

```

You can even pass multiple parameters to the scope by passing a comma separated list to the filter:

```
GET /events?filter[starts_between]=2018-01-01,2018-12-31

```

#### Custom filters

[](#custom-filters)

You can specify custom filters using the `Filter::custom()` method. Custom filters are simple, invokable classes that implement the `\Spatie\QueryBuilder\Filters\Filter` interface. This way you can create any query your heart desires.

For example:

```
use Spatie\QueryBuilder\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

class FiltersUserPermission implements Filter
{
    public function __invoke(Builder $query, $value, string $property) : Builder
    {
        return $query->whereHas('permissions', function (Builder $query) use ($value) {
            $query->where('name', $value);
        });
    }
}

use Spatie\QueryBuilder\Filter;

// GET /users?filter[permission]=createPosts
$users = QueryBuilder::for(User::class)
    ->allowedFilters(Filter::custom('permission', FiltersUserPermission::class))
    ->get();
// $users will contain all users that have the `createPosts` permission
```

### Sorting

[](#sorting)

The `sort` query parameter is used to determine by which property the results collection will be ordered. Sorting is ascending by default. Adding a hyphen (`-`) to the start of the property name will reverse the results collection.

```
// GET /users?sort=-name
$users = QueryBuilder::for(User::class)->get();

// $users will be sorted by name and descending (Z -> A)
```

By default, all model properties can be used to sort the results. However, you can use the `allowedSorts` method to limit which properties are allowed to be used in the request.

When trying to sort by a property that's not specified in `allowedSorts()` an `InvalidSortQuery` exception will be thrown.

```
// GET /users?sort=password
$users = QueryBuilder::for(User::class)
    ->allowedSorts('name')
    ->get();

// Will throw an `InvalidSortQuery` exception as `password` is not an allowed sorting property
```

To define a default sort parameter that should be applied without explicitly adding it to the request, you can use the `defaultSort` method.

```
// GET /users
$users = QueryBuilder::for(User::class)
    ->defaultSort('name')
    ->allowedSorts('name', 'street')
    ->get();

// Will retrieve the users sorted by name
```

You can also pass in an array of sorts to the `allowedSorts()` method.

```
// GET /users?sort=name
$users = QueryBuilder::for(User::class)
    ->allowedSorts(['name', 'street'])
    ->get();

// Will retrieve the users sorted by name
```

You can sort by multiple properties by separating them with a comma:

```
// GET /users?sort=name,-street
$users = QueryBuilder::for(User::class)
    ->allowedSorts('name', 'street')
    ->get();

// $users will be sorted by name in ascending order with a secondary sort on street in descending order.
```

### Selecting specific columns

[](#selecting-specific-columns)

Sometimes you'll want to fetch only a couple fields to reduce the overall size of your SQL query. This can be done using the `fields` query parameter. The following fetch only the users' `id` and `name`

```
GET /users?fields[users]=id,name

```

The SQL query will look like this:

```
SELECT "id", "name" FROM "users"
```

Selecting fields for included models works the same way. This is especially useful when including entire relationships when you only need a couple of columns. Consider the following example:

```
GET /posts?include=author&fields[author]=name

```

All posts will be fetched including only the name of the author.

### Append attributes

[](#append-attributes)

Sometimes you will want to append some custom attributes into result from a Model. This can be done using the `append` parameter.

```
class User extends Model{

    public function getFullnameAttribute()
    {
        return $this->firstname.' '.$this->lastname;
    }
}

```

```
// GET /users?append=fullname

$users = QueryBuilder::for(User::class)
    ->allowedAppends('fullname')
    ->get();

```

Of course you can pass a list of attributes to be appended.

```
// GET /users?append=fullname,ranking

```

### Other query methods

[](#other-query-methods)

As the `QueryBuilder` extends Laravel's default Eloquent query builder you can use any method or macro you like. You can also specify a base query instead of the model FQCN:

```
QueryBuilder::for(User::where('id', 42)) // base query instead of model
    ->allowedIncludes('posts')
    ->where('activated', true) // chain on any of Laravel's query methods
    ->first(); // we only need one specific user
```

#### Pagination

[](#pagination)

This package doesn't provide any methods to help you paginate responses. However as documented above you can use Laravel's default [`paginate()` method](https://laravel.com/docs/5.5/pagination).

If you want to completely adhere to the JSON API specification you can also use our own [spatie/json-api-paginate](https://github.com/spatie/laravel-json-api-paginate)!

### Building queries at the front end

[](#building-queries-at-the-front-end)

If you use [Vue](https://vuejs.org/), you might be interested in the [vue-api-query package](https://github.com/robsontenorio/vue-api-query) by [Robson Tenório](https://github.com/robsontenorio).

### Testing

[](#testing)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Postcardware
------------

[](#postcardware)

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Samberstraat 69D, 2060 Antwerp, Belgium.

We publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).

Credits
-------

[](#credits)

- [Alex Vanderbist](https://github.com/AlexVanderbist)
- [All Contributors](../../contributors)

Support us
----------

[](#support-us)

Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource).

Does your business depend on our contributions? Reach out and support us on [Patreon](https://www.patreon.com/spatie). All pledges will be dedicated to allocating workforce on maintenance and new awesome stuff.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

31

—

LowBetter than 66% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity21

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

5

Last Release

2904d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/10472206?v=4)[Barış Bora](/maintainers/barisbora)[@barisbora](https://github.com/barisbora)

---

Top Contributors

[![barisbora](https://avatars.githubusercontent.com/u/10472206?v=4)](https://github.com/barisbora "barisbora (7 commits)")

---

Tags

laravel-query-builderbarisboraburaktekin

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/barisbora-laravel-query-builder/health.svg)

```
[![Health](https://phpackages.com/badges/barisbora-laravel-query-builder/health.svg)](https://phpackages.com/packages/barisbora-laravel-query-builder)
```

###  Alternatives

[spatie/laravel-query-builder

Easily build Eloquent queries from API requests

4.5k29.4M280](/packages/spatie-laravel-query-builder)[hubspot/api-client

Hubspot API client

24015.5M18](/packages/hubspot-api-client)[pocketmine/bedrock-protocol

An implementation of the Minecraft: Bedrock Edition protocol in PHP

172437.8k11](/packages/pocketmine-bedrock-protocol)[botman/driver-telegram

Telegram driver for BotMan

94452.6k6](/packages/botman-driver-telegram)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
