PHPackages                             ambengers/query-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. [Search &amp; Filtering](/categories/search)
4. /
5. ambengers/query-filter

ActiveLibrary[Search &amp; Filtering](/categories/search)

ambengers/query-filter
======================

Laravel package for filtering resources with request query string

4.9.2(2y ago)3513.9k↑15.6%7MITPHPPHP ^7.1|^8.0CI failing

Since Sep 21Pushed 2y ago2 watchersCompare

[ Source](https://github.com/ambengers/laravel-query-filter)[ Packagist](https://packagist.org/packages/ambengers/query-filter)[ RSS](/packages/ambengers-query-filter/feed)WikiDiscussions master Synced 2d ago

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

Laravel Query Filter
====================

[](#laravel-query-filter)

This packages provides an elegant way to filter your eloquent models via the request query string.

Inspired by [Laracasts](https://laracasts.com/series/eloquent-techniques/episodes/4)

[![Build Status](https://camo.githubusercontent.com/00b9733bcec356abd101024f4e15ea90b2cbe00e655ecd94265d0430cb93a516/68747470733a2f2f7472617669732d63692e6f72672f616d62656e676572732f6c61726176656c2d71756572792d66696c7465722e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/ambengers/laravel-query-filter)[![StyleCI](https://camo.githubusercontent.com/252904f1051f9713cc299e0b0a99728bb5a485a2b52f8289c60d3a0fb3b8c023/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3134393736373138392f736869656c643f6272616e63683d6d6173746572)](https://github.styleci.io/repos/149767189)

Features
========

[](#features)

This packages allows you to create filters via the request query string. Out of the box, this package also features sorting, pagination and search for your eloquent models.

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

[](#installation)

Run the following command in the terminal.

```
composer require ambengers/query-filter
```

Then publish the config file by running the following command.

```
php artisan vendor:publish --tag=query-filter-config
```

The config file contains the configuration for the namespace and path of the filter classes. The default namespace is `App\Filters` and default path is `app/Filters`.

Usage
=====

[](#usage)

Method-based Filters
--------------------

[](#method-based-filters)

You can generate a filter class using the `make:query-filter` command.

```
php artisan make:query-filter PostFilter
```

In the filter class, you can also define your own custom filters. For example, lets add a filter for `/posts?published` to get only the published posts:

```
use Ambengers\QueryFilter\AbstractQueryFilter;

class PostFilter extends AbstractQueryFilter
{
  /**
   * Filter the post to get the published ones
   *
   * @return Illuminate\Database\Eloquent\Builder
   */
  public function published()
  {
    return $this->builder->whereNotNull('published_at');
  }
}
```

Now, you can apply the filter on your controller. For example:

```
use App\Filters\PostFilter;

class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index(PostFilter $filters)
  {
    $posts = Post::filter($filters);

    return PostResource::collection($posts);
  }
}
```

Object-based Filters
--------------------

[](#object-based-filters)

If you like a more object oriented approach for creating your filters, you can create a `$filters` array in your Filter class to declare your filters.

```
use Ambengers\QueryFilter\AbstractQueryFilter;

class PostFilter extends AbstractQueryFilter
{
  /**
   * List of filters.
   *
   * @var array
   */
  protected $filters = [
    'published' =>  \App\Filters\Published::class,
  ];
}
```

`$filters` array will receive a key-value pair in which the key is the param in your query string and the value is the filter object that will handle the filtering.

Then you can use the `make:query-filter-object` command to generate your filter object. Note: filter objects will use the same namespace as your filter class.

```
php artisan make:query-filter-object Published
```

The filter object is a simple invokable class that accepts the `Eloquent\Builder` as first parameter and the query string value as the second parameter. Include the filter logic in the invoke method, like so.

```
use Illuminate\Database\Eloquent\Builder;

class Published
{
  /**
   * Handle the filtering
   *
   * @param  Illuminate\Database\Eloquent\Builder $builder
   * @param  string|null  $value
   * @return Illuminate\Database\Eloquent\Builder
   */
  public function __invokable(Builder $builder, $value = null)
  {
    $builder->whereNotNull('published_at');
  }
}
```

Sorting
-------

[](#sorting)

This package also allows you to sort your models by following `field|direction` syntax, like so.

```
/** Sorting */
/posts?sort=created_at|desc
```

Pagination
----------

[](#pagination)

This package also allows you to paginate your models like so.

```
/** Pagination */
/posts?page=2
```

Behind the scenes, it uses Laravel's own pagination, which the default `per_page` size is 15. Of course, you can override this behaviour like so.

```
/** Pagination */
/posts?page=2&per_page=10
```

Note: If pagination keys are not present on the request query string, it will return a collection result.

Search
------

[](#search)

This package also allows you to define the columns that are searchable. By default, when you generate a filter class with `make:query-filter` command, the class will contain a `$searchableColumns` array. Then, list the searchable columns of your model in this array.

```
class PostFilter extends AbstractQueryFilter
{
  /**
   * List of searchable columns
   *
   * @var array
   */
  protected $searchableColumns = ['subject', 'body'];
}
```

Searchable Relationship Columns
-------------------------------

[](#searchable-relationship-columns)

The `$searchableColumns` can also accept a key value pair if you want your model to be searchable using relationship fields:

```
class PostFilter extends AbstractQueryFilter
{
  /**
   * List of searchable columns
   *
   * @var array
   */
  protected $searchableColumns = [
    'subject',
    'body',
    'comments' => ['body'],
  ];
}
```

Loadable Relationships
----------------------

[](#loadable-relationships)

This packages allows you to load relationships of models using the query string. First, use the `make:query-loader` command to create your loader class.

```
php artisan make:query-loader PostLoader
```

Then, declare the loader class within your filter class.

```
use App\Loaders\PostLoader;

class PostFilter extends AbstractQueryFilter
{
  /**
   * Loader class
   *
   * @var string
   */
   protected $loader = PostLoader::class;
}
```

Then on the loader class, declare the relationships that can be eager/lazy-loaded within `$loadables` array.

```
class PostLoader extends AbstractQueryLoader
{
    /**
     * Relationships that can be lazy/eager loaded
     *
     * @var array
     */
    protected $loadables = [
        'comments', 'author'
    ];
}
```

And that's it! Now use the `load` param on your query string to load relationships.

```
/posts?load=comments,author
```

Note: Relationships with multiple words can be declared using either camel or snake case within the `$loadables` array. The package will automatically convert the relationships into snake case which is typically how you will write your relationship methods. Also, relationships that are not declared in `$loadables` array will not be eager-loaded even if used in query string.

Using Loader On The Controller@show Action
------------------------------------------

[](#using-loader-on-the-controllershow-action)

`Controller@show` action will typically return a single model instance instead of a collection. However, there are cases that you will need an ability to optionally load relationships via query string as well.

Inject your loader class as an argument to your `show` method, then call the `filter` method on your and pass the loader instance.

```
class PostController extends Controller
{
    /**
     * Display the specified resource.
     *
     * @param App\Models\Post $post
     * @param App\Loaders\PostLoader $loader
     * @return Illuminate\Http\JsonResponse
     */
    public function show(Post $post, PostLoader $loader)
    {
        $post = $post->filter($loader);

        return response()->json($post);
    }
}
```

Now you should be able to load your relationships from your query string.

```
/posts/1?load=comments,author
```

Including Soft Delete Constraints
---------------------------------

[](#including-soft-delete-constraints)

Include soft deleted constraits when requesting for eager loaded models using the pipe symbol.

```
/posts/1?load=comments|withTrashed // comments will include soft deleted models
/posts/1?load=comments|onlyTrashed // comments will include only soft deleted models
```

Preventing Method Name Clash
----------------------------

[](#preventing-method-name-clash)

To customize the method name you call on your model to use the query filter, just update the value of the `method` key in the query\_filter config file.

```
return [
    // The method to call to use the query filter
    'method' => 'fooBar', // Now call $post->fooBar($loaders)
...
]
```

With [Laravel Livewire](https://github.com/livewire/livewire)
-------------------------------------------------------------

[](#with-laravel-livewire)

Livewire follows its own structure when sending requests to the backend. This makes it impossible for query-filter package to automatically read parameters from the request query string.

However, you can still manually assign parameters during runtime by resolving your query filter class from the container and set the `parameters` like so...

```
public function render () {
    $filters = app(PostFilter::class)->parameters(['search' => 'foo']);

    $posts = Post::filter($filters);

    return view('livewire.posts.index', ['posts' => $posts]);
}
```

Similar Packages
----------------

[](#similar-packages)

[cerbero90/query-filters](https://github.com/cerbero90/query-filters)

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity36

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity78

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

Recently: every ~236 days

Total

28

Last Release

1037d ago

Major Versions

1.1.2 → 2.0.02019-01-24

2.0.4 → 3.0.12019-02-25

3.3 → 4.02019-04-12

PHP version history (3 changes)v1.0.1PHP ^7.0

3.2PHP ^7.1

4.7PHP ^7.1|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/545ea2630b623d1556d595190fc55b0a32731291629f2378c632bcf0dd3164c2?d=identicon)[ambengers](/maintainers/ambengers)

---

Top Contributors

[![ambengers](https://avatars.githubusercontent.com/u/17848299?v=4)](https://github.com/ambengers "ambengers (63 commits)")

---

Tags

laravelqueryfilter

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ambengers-query-filter/health.svg)

```
[![Health](https://phpackages.com/badges/ambengers-query-filter/health.svg)](https://phpackages.com/packages/ambengers-query-filter)
```

###  Alternatives

[mehradsadeghi/laravel-filter-querystring

Filter your queries based on url query string parameters like a breeze.

168128.5k](/packages/mehradsadeghi-laravel-filter-querystring)[hashemi/queryfilter

A simple &amp; dynamic package for your eloquent query in laravel. It will help you to write query logic individual for each parameter.

391.2k](/packages/hashemi-queryfilter)[pos-lifestyle/laravel-nova-date-range-filter

A Laravel Nova date range filter.

16181.8k](/packages/pos-lifestyle-laravel-nova-date-range-filter)[tapp/filament-value-range-filter

Filament country code field.

2481.4k](/packages/tapp-filament-value-range-filter)

PHPackages © 2026

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