PHPackages                             matthenning/eloquent-api-filter - 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. matthenning/eloquent-api-filter

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

matthenning/eloquent-api-filter
===============================

Awesome and simple way to filter Eloquent queries right from the API URL without the clutter.

v3.0.1(2y ago)104.9k3[1 issues](https://github.com/matthenning/eloquent-api-filter/issues)[1 PRs](https://github.com/matthenning/eloquent-api-filter/pulls)GPL-3.0PHPPHP &gt;=8.2

Since Apr 5Pushed 2y ago1 watchersCompare

[ Source](https://github.com/matthenning/eloquent-api-filter)[ Packagist](https://packagist.org/packages/matthenning/eloquent-api-filter)[ RSS](/packages/matthenning-eloquent-api-filter/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (10)Dependencies (4)Versions (19)Used By (0)

 [![](logo.png)](logo.png)

Eloquent API Filter
===================

[](#eloquent-api-filter)

Awesome and simple way to create, query and modify Eloquent models through your API - with only a few lines of code.

Concept
=======

[](#concept)

When developing API applications, you'll often end up with lots of duplicate code within your controllers. Eloquent API Filter offers a simple way to expose your models through the API by defining a route and a tiny controller. Your controller only needs to use a few traits and you'll have a full CRUD implementation for your model exposed through you API.

Table of Contents
-----------------

[](#table-of-contents)

- [Concept](#concept)
- [Installation](#installation)
- [Queries](#queries)
- [Responses](#responses)
- [What if I need more?](#what-if-i-need-more)

Installation
============

[](#installation)

Package installation
--------------------

[](#package-installation)

```
composer require matthenning/eloquent-api-filter
```

Controller setup
----------------

[](#controller-setup)

You have the choice to use either of the following methods to leverage the filter. The easiest method out of the box is to simply extend the included controller.

### Option 1: Extend the controller (recommended)

[](#option-1-extend-the-controller-recommended)

The easiest way to use the Eloquent API Filter is to extend its controller. For this example, let's say you have a model named Person. You'll just have to create a matching controller and use the included traits to enable the default methods for index, show, store, update, destroy:

```
use Matthenning\EloquentApiFilter\Controller;

class PersonController extends Controller
{
    use UsesDefaultIndexMethodTrait,
        UsesDefaultShowMethodTrait,
        UsesDefaultStoreMethodTrait,
        UsesDefaultUpdateMethodTrait,
        UsesDefaultDestroyMethodTrait;

}
```

Next you can expose your controller by adding a new route:

```
Route::resource('persons', \App\Http\Controllers\PersonController::class);
```

Eloquent API Filter will automatically find the matching model class as long as you follow the naming scheme of this example. If you have custom names or namespaces, you can override the modelName property within your controller:

```
protected ?string $modelName = Person::class;
```

And you're done! Start querying your API following the method guidelines. See  for actions store, show, index, update, destroy:

```
POST /api/persons
{
    "name": "Alexander",
    "age": 23
}

GET /api/persons/1

GET /api/persons/?filter[age]=23

PUT /api/persons/1
{
    "age": 24
}

DELETE /api/persons/1
```

#### Custom Resource

[](#custom-resource)

If you're using custom resources () you can define a resourceName property on your models. Otherwise the default resource will be used. Make sure to override the toArray and call enrich() with your data. The enrich method will make sure all eager loaded relations (/model?with\[\]=relation1,relation2) are also transformed by their respective resource.

In your Person model:

```
public static ?string $resourceName = PersonResource::class;
```

In your PersonResource:

```
class PersonResource extends \Matthenning\EloquentApiFilter\Resource
{

    public function toArray(Request $request): array
    {
        return $this->enrich([
            'id' => $this->resource->id,
            // ... map your fields here
        ]);
    }

}
```

### Option 2: Use the trait

[](#option-2-use-the-trait)

If you'd like to handle the controller and resource logic yourself entirely, can use the FiltersEloquentApi trait in your controller.

```
class PersonController extends Matthenning\EloquentApiFilter\Controller
{

    use Matthenning\EloquentApiFilter\Traits\FiltersEloquentApi;

    public function index(Request $request)
    {
        $persons = Person::query();

        return $this->filterApiRequest($request, $persons);
    }
}
```

### Option 3: Query the filter directly

[](#option-3-query-the-filter-directly)

If traits are not to your taste you can also initialize Eloquent API Filter yourself.

```
use Matthenning\EloquentApiFilter\EloquentApiFilter;

class PersonController extends Controller
{
    public function index(Request $request)
    {
        $query = Person::query();

        $filtered = (new EloquentApiFilter($request, $query))->filter();

        return $filtered->get();
    }
}
```

Queries
=======

[](#queries)

Filtering
---------

[](#filtering)

### URL Syntax

[](#url-syntax)

Filter with specific operator:

```
GET /model?filter[field]=operator:comparison
```

Filter for equality:

```
GET /model?filter[field]=operator
```

### Operators:

[](#operators)

- eq (equal, can be omitted)
- ne (not equal)
- ge (greater or equal)
- gt (greater)
- le (lower or equal)
- lt (lower)
- in (expects a comma separated array as value)
- notin (expects a comma separated array as value)
- null
- notnull,
- like
- notlike
- today (for timestamps)
- nottoday (for timestamps)

### Examples

[](#examples)

Matches all entities where name starts with Rob and deceased is null:

```
GET /persons?filter[name]=like:Rob*&filter[deceased]=null:
```

Multiple filters on one field can be chained. Matches all entities where created\_at is between 2016-12-10 and 2016-12-08:

```
GET /persons?filter[created_at]=lt:2016-12-10:and:gt:2016-12-08`
```

Filter by related models' fields by using the dot-notaion. Matches all Posts of Persons where Post name contains "API"

```
GET /persons?filter[posts.name]=like:*API*
```

Get all persons with name Rob and Bob

```
GET /persons?filter[name]=in:Rob,Bob
```

### Special filters

[](#special-filters)

#### Timestamps

[](#timestamps)

Matches all persons whos' birthdays are today

```
GET /persons?filter[birthday]=today
```

Sorting
-------

[](#sorting)

### URL Syntax

[](#url-syntax-1)

```
GET /model?orderBy[field]=direction
```

### Examples

[](#examples-1)

Limit and sorting. Matches the top 10 persons with age of 21 or older sorted by name in ascending order

```
GET /persons?filter[age]=ge:21&order[name]=asc&limit=10
```

Select fields
-------------

[](#select-fields)

Select only specific columns. Might need additional work on your model transformation.

### URL Syntax

[](#url-syntax-2)

```
GET /model?select=column1,column2
```

### Examples

[](#examples-2)

```
GET /persons?select=name,email
```

Joins
-----

[](#joins)

### URL Syntax

[](#url-syntax-3)

```
GET /model?with[]=relation1
GET /model?with[]=relation1&filter[relation1.field]=operator:comparison
```

### Examples

[](#examples-3)

Join posts-relation on persons

```
GET /persons?with[]=posts
```

Complex filter values
---------------------

[](#complex-filter-values)

If you need to filter for a value with special characters, you can base64 encode the field to avoid breaking the filter syntax.

### URL Syntax

[](#url-syntax-4)

```
GET /model?filter[field]={{b64(value)}}
```

### Examples

[](#examples-4)

```
GET /model?filter[field]=lt:{{b64(MjAxNy0wNy0yMiAyMzo1OTo1OQ==)}}
```

Responses
=========

[](#responses)

Responses always contain two JSON objects data and meta. Data contains the queried models and meta contains for example pagination details.

### Example

[](#example)

```
{
    "meta": {
        "pagination": {
            "items": 10,
            "total_items": 113,
            "total_pages": 12,
            "current_page": 1,
            "per_page": 10
        }
    },
    "data": [
        {
            "id": 1,
            "name": "Alexander",
            "age": 23
        },
        { /*...*/ }, { /*...*/ }
    ]
}
```

What if I need more?
====================

[](#what-if-i-need-more)

In case you need complex queries which are not covered by this library, you can use the EloquentApiFilter trait in your custom controller and further filter the query before retrieving the models. That way you can still use the filter features and only need to add your custom filtering before returning the retrieved models.

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity26

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity84

Battle-tested with a long release history

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

Recently: every ~263 days

Total

15

Last Release

883d ago

Major Versions

v1.5 → v2.02021-03-06

v2.1 → v3.02023-09-18

PHP version history (3 changes)1.0.0PHP &gt;=5.6.4

v2.0PHP &gt;=8.0

v3.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/3c584c2c47897eef224ea12b1b5dd90a8c9b2a150a288f0b95379b2133584b31?d=identicon)[matthenning](/maintainers/matthenning)

---

Top Contributors

[![rustyricky](https://avatars.githubusercontent.com/u/5699183?v=4)](https://github.com/rustyricky "rustyricky (33 commits)")

---

Tags

apieloquenteloquent-ormeloquent-relationshipslaravellaravel-frameworkapilaraveleloquentfilterfiltering

### Embed Badge

![Health badge](/badges/matthenning-eloquent-api-filter/health.svg)

```
[![Health](https://phpackages.com/badges/matthenning-eloquent-api-filter/health.svg)](https://phpackages.com/packages/matthenning-eloquent-api-filter)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k29.9M42](/packages/kirschbaum-development-eloquent-power-joins)[api-platform/laravel

API Platform support for Laravel

59156.3k11](/packages/api-platform-laravel)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1232.2k16](/packages/fleetbase-core-api)[ntanduy/cloudflare-d1-database

Cloudflare D1 database driver for Laravel — full Eloquent &amp; Query Builder support.

276.8k](/packages/ntanduy-cloudflare-d1-database)

PHPackages © 2026

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