PHPackages                             psenna/lumen-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. [Database &amp; ORM](/categories/database)
4. /
5. psenna/lumen-query-builder

ActiveLibrary[Database &amp; ORM](/categories/database)

psenna/lumen-query-builder
==========================

Easily build Eloquent queries from API requests

7.0.0(5y ago)358421MITPHPPHP ^7.2

Since Jan 16Pushed 5y ago2 watchersCompare

[ Source](https://github.com/psenna/lumen-query-builder)[ Packagist](https://packagist.org/packages/psenna/lumen-query-builder)[ Docs](https://github.com/spatie/laravel-query-builder)[ RSS](/packages/psenna-lumen-query-builder/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (10)Dependencies (5)Versions (50)Used By (1)

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
```

#### Property Column Alias

[](#property-column-alias)

It can be useful to expose properties for filtering, that do not share the exact naming of your database column. If you wanted to allow filtering on columns that may have a prefix in the database, you can use the following notation.

```
use Spatie\QueryBuilder\Filter;

// GET /users?filter[name]=John
$users = QueryBuilder::for(User::class)
	->allowedFilters(Filter::exact('name', 'user_name')) // public filter, column name
    ->get();
// filter by the column 'user_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', '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"
```

Using the `allowedFields` method you can limit which fields (columns) are allowed to be queried in the request.

When trying to select a column that's not specified in `allowedFields()` an `InvalidFieldQuery` exception will be thrown.

```
$users = QueryBuilder::for(User::class)
    ->allowedFields('name')
    ->get();

// GET /users?fields[users]=email will throw an `InvalidFieldQuery` exception as `email` is not an allowed field.
```

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

35

—

LowBetter than 79% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community25

Small or concentrated contributor base

Maturity71

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~19 days

Recently: every ~56 days

Total

45

Last Release

2170d ago

Major Versions

0.0.3 → 1.0.02018-01-17

1.12.7 → 2.0.02020-01-30

2.0.2 → 7.0.02020-06-05

PHP version history (2 changes)0.0.1PHP ^7.1

1.12.7PHP ^7.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/ff3ba85a96c1be91c899fa9f9db64193398e764f61f369672e0f6b72e4825cc3?d=identicon)[psenna](/maintainers/psenna)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (71 commits)")[![AlexVanderbist](https://avatars.githubusercontent.com/u/6287961?v=4)](https://github.com/AlexVanderbist "AlexVanderbist (67 commits)")[![psenna](https://avatars.githubusercontent.com/u/4554891?v=4)](https://github.com/psenna "psenna (15 commits)")[![cornelp](https://avatars.githubusercontent.com/u/10222052?v=4)](https://github.com/cornelp "cornelp (6 commits)")[![brendt](https://avatars.githubusercontent.com/u/6905297?v=4)](https://github.com/brendt "brendt (5 commits)")[![ntzm](https://avatars.githubusercontent.com/u/3888578?v=4)](https://github.com/ntzm "ntzm (4 commits)")[![vyuldashev](https://avatars.githubusercontent.com/u/1809081?v=4)](https://github.com/vyuldashev "vyuldashev (4 commits)")[![robsontenorio](https://avatars.githubusercontent.com/u/118955?v=4)](https://github.com/robsontenorio "robsontenorio (3 commits)")[![oanhnn](https://avatars.githubusercontent.com/u/1757120?v=4)](https://github.com/oanhnn "oanhnn (3 commits)")[![spyric](https://avatars.githubusercontent.com/u/2044754?v=4)](https://github.com/spyric "spyric (2 commits)")[![mpociot](https://avatars.githubusercontent.com/u/804684?v=4)](https://github.com/mpociot "mpociot (2 commits)")[![josiasmontag](https://avatars.githubusercontent.com/u/1945577?v=4)](https://github.com/josiasmontag "josiasmontag (1 commits)")[![ndnam90](https://avatars.githubusercontent.com/u/5795738?v=4)](https://github.com/ndnam90 "ndnam90 (1 commits)")[![NickToony](https://avatars.githubusercontent.com/u/6717505?v=4)](https://github.com/NickToony "NickToony (1 commits)")[![ce-brex](https://avatars.githubusercontent.com/u/28264129?v=4)](https://github.com/ce-brex "ce-brex (1 commits)")[![ospang](https://avatars.githubusercontent.com/u/31650530?v=4)](https://github.com/ospang "ospang (1 commits)")[![pactode](https://avatars.githubusercontent.com/u/5956778?v=4)](https://github.com/pactode "pactode (1 commits)")[![blueclock](https://avatars.githubusercontent.com/u/586174?v=4)](https://github.com/blueclock "blueclock (1 commits)")[![rainerkent](https://avatars.githubusercontent.com/u/17761544?v=4)](https://github.com/rainerkent "rainerkent (1 commits)")[![richardkeep](https://avatars.githubusercontent.com/u/3874381?v=4)](https://github.com/richardkeep "richardkeep (1 commits)")

---

Tags

spatielaravel-query-builder

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/psenna-lumen-query-builder/health.svg)

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

###  Alternatives

[spatie/laravel-query-builder

Easily build Eloquent queries from API requests

4.4k26.9M220](/packages/spatie-laravel-query-builder)[spatie/laravel-sluggable

Generate slugs when saving Eloquent models

1.6k11.5M223](/packages/spatie-laravel-sluggable)[spatie/laravel-medialibrary

Associate files with Eloquent models

6.1k37.7M472](/packages/spatie-laravel-medialibrary)[spatie/laravel-backup

A Laravel package to backup your application

6.0k21.8M191](/packages/spatie-laravel-backup)[spatie/laravel-translatable

A trait to make an Eloquent model hold translations

2.4k23.0M413](/packages/spatie-laravel-translatable)[spatie/laravel-model-states

State support for Eloquent models

1.3k6.2M27](/packages/spatie-laravel-model-states)

PHPackages © 2026

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