PHPackages                             obrainwave/laravel-query-filters - 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. obrainwave/laravel-query-filters

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

obrainwave/laravel-query-filters
================================

A lightweight Laravel search and filter package with global search, aliases, and relationship filtering.

v1.0.3(8mo ago)06[3 PRs](https://github.com/Obrainwave/laravel-query-filters/pulls)MITPHPPHP ^8.0CI passing

Since Aug 31Pushed 1mo agoCompare

[ Source](https://github.com/Obrainwave/laravel-query-filters)[ Packagist](https://packagist.org/packages/obrainwave/laravel-query-filters)[ Docs](https://github.com/obrainwave/laravel-query-filters)[ GitHub Sponsors](https://github.com/:vendor_name)[ RSS](/packages/obrainwave-laravel-query-filters/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (10)Versions (8)Used By (0)

Laravel Query Filters
=====================

[](#laravel-query-filters)

A lightweight Laravel package for advanced Eloquent filtering, including **global search, relationship filtering, operators, pagination, sorting, and custom filter classes**.

---

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

[](#installation)

```
composer require obrainwave/laravel-query-filters
```

Publish the config (optional):

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

---

Configuration
-------------

[](#configuration)

All defaults are in `config/query-filters.php`:

```
return [

    'global_key' => 'q', // Query parameter key for global search

    'allowed_filters' => ['name', 'role'],

    'default_match' => 'exact', // exact, like, strict

    'filter_modes' => [
        // Custom per-filter matching, supports wildcards
        // 'email' => 'strict',
        // 'user.*' => 'like',
        // '*.status' => 'strict',
    ],

    'pagination' => [
        'per_page' => 10,
        'max_per_page' => 100,
    ],

    'sorting' => [
        'allowed_columns' => [], // e.g. ['name', 'created_at']
        'default' => null,       // e.g. 'created_at' or '-created_at'
    ],

    'operators' => [
        'enabled' => true,       // Enable operator-based filters
    ],

];
```

---

Basic Usage
-----------

[](#basic-usage)

You can filter Eloquent models directly using the `filter()` scope.

To use the query filters in your Laravel models, you must add the Filterable trait to the model. For example:

```
use Illuminate\Database\Eloquent\Model;
use Obrainwave\LaravelQueryFilters\Filterable;

class User extends Model
{
    use Filterable;

    // Optional: define allowed columns in the model
    // protected $allowedFilters = ['name', 'email'];
}
```

Once the trait is added, you can call the `filter()` method on your model statically:

```
use App\Models\User;

$users = User::filter([
    'status' => 'active',
    'role' => 'admin',
    'q' => 'john', // Global search
])->get(); // or ->first()
```

- Without Filterable, `filter()` won’t exist on your model.
- You can optionally define $allowedFilters in the model or rely on the config for auto-generated filters. If your `$allowedFilters` is protected, you have to define a public get method to access it. For example:

```
    protected array $allowedFilters = ['status', 'name', 'role'];

    public function getAllowedFilters(): array
    {
        return $this->allowedFilters;
    }
```

If you know what you are doing, you can probably just leave `$allowedFilters` as public property

```
public array $allowedFilters = ['status', 'name', 'role'];
```

Or you can actually allow all table columns to be filtered by setting the default value in `config/query-filters.php`

```
'allowed_filters'      => ['*']
```

And also supports laravel paginate and simplePaginate

```
$users = User::filter([
    'status' => 'active',
    'role' => 'admin',
    'q' => 'john', // Global search
])->paginate(); // or simplePaginate() | Supports per_page from request or config
```

### URL Parameters

[](#url-parameters)

Filters also work directly from URL query parameters:

```
/users?status=active&role=admin&q=john&per_page=5&sort=-created_at

```

Which you can pass directly from your request helper or injected `Illuminate\Http\Request`

```
use App\Models\User;

$users = User::filter(request())->paginate(); // Supports per_page from request or config
```

---

### Using Laravel Query Methods

[](#using-laravel-query-methods)

After applying filters with the package, you can continue to use all standard Laravel query builder and Eloquent methods. For example:

```
$users = User::filter($filters)->get();
$users = User::filter($filters)->paginate(15);
$users = User::filter($filters)->simplePaginate(10);
$user  = User::filter($filters)->first();
```

- `->get()` → retrieves all matching records.
- `->paginate()` → retrieves paginated results with page links.
- `->simplePaginate()` → retrieves simpler pagination without total count.
- `->first()` → retrieves the first matching record.

This allows you to combine filtering with any Laravel query workflow seamlessly.

---

Features
--------

[](#features)

### 1. **Global Search**

[](#1-global-search)

Search across multiple columns using a single query parameter:

```
$users = User::filter(['q' => 'john'])->get();
```

Customize global search columns in your model:

```
protected array $globalSearchColumns = ['name', 'email'];
```

Or provide a method:

```
public function getGlobalSearchColumns(): array
{
    return ['name', 'email', 'username'];
}
```

---

### 2. **Allowed Filters**

[](#2-allowed-filters)

Only specified filters are applied:

```
protected array $allowedFilters = ['status', 'role', 'email'];
```

You can also set global defaults in the config.

---

### 3. **Operators**

[](#3-operators)

Filter with operators like `gt`, `gte`, `lt`, `lte`, `between`, and `like`:

```
$users = User::filter([
    'created_at' => ['gte' => '2025-01-01'],
    'age' => ['between' => [20, 30]]
])->get();
```

---

### 4. **Relationship Filtering**

[](#4-relationship-filtering)

Filter nested relationships using dot notation:

```
$users = User::filter([
    'posts.title' => 'My Post',
    'or:posts.comments.body' => 'Great',
])->with(['posts.comments'])->paginate();
```

- Use `or:` prefix for OR conditions.
- Supports arrays of values (multiple OR conditions).
- Supports operators (gt, lt, between, like).

It also supports relationship filtering and can accept arrays of values. This allows you to filter related models based on multiple possible values. For example:

```
$users = User::filter([
    'posts.title' => ['My Post', 'Laravel'],
    'or:posts.comments.body' => ['Great', 'Child filtering', 'Package'],
])
->with(['posts.comments'])
->paginate();
```

---

### 5. **Sorting**

[](#5-sorting)

Sort using query string or programmatically:

```
$users = User::filter(['sort' => 'name,-created_at'])->get();
```

- Prefix `-` for descending.
- Only columns defined in `allowed_columns` are applied.

---

### 6. **Pagination**

[](#6-pagination)

Pagination works out-of-the-box with per-page overrides:

```
$users = User::filter(request())->paginate(); // Defaults
$users = User::filter(request())->paginate(10); // Force per_page
```

OR

```
$users = User::filter(request())->simplePaginate(); // Defaults
$users = User::filter(request())->simplePaginate(10); // Force per_page
```

- `per_page` from URL has top priority.
- Config default is fallback.
- `max_per_page` is enforced.

---

### 7. **Custom Filter Classes**

[](#7-custom-filter-classes)

If you need full control, generate a filter class and handle your custom logic in it:

The auto method automatically generates filters for your model. It uses either the model’s database columns or the columns you specify in the config, so you can quickly enable filtering without defining each field manually.

```
php artisan make:filter UserFilter
```

Example `UserFilter`:

```
namespace App\Filters;

use Obrainwave\LaravelQueryFilters\QueryFilter;

class UserFilter extends QueryFilter
{
    public function role($value)
    {
        $this->builder->where('role', $value); //You can alter this to
        return $this;
    }

    public function status($value)
    {
        $this->builder->where('status', $value);
        return $this;
    }
}
```

Then use automatically by chaining your class method(s) to your model:

```
$users = User::filter(request())->paginate();
```

- Your filter class is detected by convention (`UserFilter` for `User` model).
- All features (pagination, sorting, relationships, operators) work seamlessly.
- Supports **chaining**:

```
$users = User::filter(['role' => 'admin'])
    ->status('inactive')
    ->role('user')
    ->with('posts')
    ->paginate();
```

---

### 8. **Chaining**

[](#8-chaining)

The filter returns a query builder proxy, so you can chain additional methods from your Custom Filter Class:

```
$users = User::filter([
    'role' => 'admin',
    'status' => 'active',
])
->with(['posts.comments'])
->status('inactive')
->role('user')
->paginate();
```

---

### 9. **Case-insensitive Filtering**

[](#9-case-insensitive-filtering)

By default, filters are **case-insensitive** (`exact` or `like`) except when configured otherwise (`strict`).

---

### 10. **Extending &amp; Customization**

[](#10-extending--customization)

- Override `getAllowedFilters()` in your model.
- Override `getGlobalSearchKey()` or `$globalSearchKey` in your model.
- Override `getGlobalSearchColumns()` or `$globalSearchColumns`.
- Define per-filter matching using `filter_modes` config.

---

### Example: Full Feature Usage

[](#example-full-feature-usage)

```
$users = User::filter([
    'role' => 'admin',
    'status' => 'active',
    'posts.comments.body' => 'Great',
    'sort' => '-created_at',
    'per_page' => 5
])
->with(['posts.comments'])
->paginate();
```

---

### Installation Notes

[](#installation-notes)

- Requires **PHP 8+**
- Supports **Laravel 9, 10, 11, 12**
- No additional dependencies for filtering.
- Works out-of-the-box with Eloquent models.

---

### License

[](#license)

MIT License.

---

### Contributing

[](#contributing)

We welcome contributions from everyone! If you have ideas, bug fixes, or improvements, feel free to open an issue or submit a pull request. Whether it’s enhancing filters, adding new features, or improving documentation, your contributions are highly appreciated.

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance76

Regular maintenance activity

Popularity4

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 58.1% 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 ~0 days

Total

4

Last Release

259d ago

### Community

Maintainers

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

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (376 commits)")[![mvdnbrk](https://avatars.githubusercontent.com/u/802681?v=4)](https://github.com/mvdnbrk "mvdnbrk (46 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (30 commits)")[![Obrainwave](https://avatars.githubusercontent.com/u/40363034?v=4)](https://github.com/Obrainwave "Obrainwave (27 commits)")[![Nielsvanpach](https://avatars.githubusercontent.com/u/10651054?v=4)](https://github.com/Nielsvanpach "Nielsvanpach (23 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (20 commits)")[![pforret](https://avatars.githubusercontent.com/u/474312?v=4)](https://github.com/pforret "pforret (16 commits)")[![sebastiandedeyne](https://avatars.githubusercontent.com/u/1561079?v=4)](https://github.com/sebastiandedeyne "sebastiandedeyne (14 commits)")[![riasvdv](https://avatars.githubusercontent.com/u/3626559?v=4)](https://github.com/riasvdv "riasvdv (10 commits)")[![patinthehat](https://avatars.githubusercontent.com/u/5508707?v=4)](https://github.com/patinthehat "patinthehat (10 commits)")[![AdrianMrn](https://avatars.githubusercontent.com/u/12762044?v=4)](https://github.com/AdrianMrn "AdrianMrn (8 commits)")[![crynobone](https://avatars.githubusercontent.com/u/172966?v=4)](https://github.com/crynobone "crynobone (8 commits)")[![AlexVanderbist](https://avatars.githubusercontent.com/u/6287961?v=4)](https://github.com/AlexVanderbist "AlexVanderbist (7 commits)")[![irfanm96](https://avatars.githubusercontent.com/u/42065936?v=4)](https://github.com/irfanm96 "irfanm96 (5 commits)")[![thecaliskan](https://avatars.githubusercontent.com/u/13554944?v=4)](https://github.com/thecaliskan "thecaliskan (5 commits)")[![IGedeon](https://avatars.githubusercontent.com/u/694313?v=4)](https://github.com/IGedeon "IGedeon (4 commits)")[![abenerd](https://avatars.githubusercontent.com/u/7523903?v=4)](https://github.com/abenerd "abenerd (3 commits)")[![jessarcher](https://avatars.githubusercontent.com/u/4977161?v=4)](https://github.com/jessarcher "jessarcher (3 commits)")[![koossaayy](https://avatars.githubusercontent.com/u/6431084?v=4)](https://github.com/koossaayy "koossaayy (3 commits)")[![lloricode](https://avatars.githubusercontent.com/u/8251344?v=4)](https://github.com/lloricode "lloricode (3 commits)")

---

Tags

easy-querylaravel-packagequery-builderlaravelobrainwavelaravel-query-filters

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/obrainwave-laravel-query-filters/health.svg)

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

###  Alternatives

[mailerlite/laravel-elasticsearch

An easy way to use the official PHP ElasticSearch client in your Laravel applications.

934529.3k2](/packages/mailerlite-laravel-elasticsearch)[jeroen-g/explorer

Next-gen Elasticsearch driver for Laravel Scout.

397612.3k](/packages/jeroen-g-explorer)[spatie/laravel-prometheus

Export Laravel metrics to Prometheus

2651.3M6](/packages/spatie-laravel-prometheus)[spatie/laravel-site-search

A site search engine

300129.1k](/packages/spatie-laravel-site-search)[romanstruk/manticore-scout-engine

Laravel Manticore Scout Engine

4818.1k](/packages/romanstruk-manticore-scout-engine)[internachi/blade-alpine-instantsearch

Algolia instant search as Blade/Alpine.js components

1940.9k](/packages/internachi-blade-alpine-instantsearch)

PHPackages © 2026

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