laratribe/laravel-advanced-filters

Advanced column filters for Laravel. Text, numeric, date and set filters with custom operators and strict allow-listing — declared once on an Eloquent model, then rendered with Blade + Alpine, Livewire, Inertia or as a JSON API.
2
Install
composer require laratribe/laravel-advanced-filters
Latest Version:v1.0.0
PHP:^8.2
License:MIT
Last Updated:Sep 22, 2026
Links: GitHub  ·  Packagist
Maintainer: rnsharma93

Laravel Advanced Filters

tests Latest Version License

Declare filters once on an Eloquent model, then render them with Blade + Alpine, Livewire, Inertia (Vue/React), or no UI at all as a JSON API.

📖 Documentation  ·  🚀 Live demo  ·  💻 Demo source

The demo is one model with seven filters, driving a Blade + Alpine page, a Livewire page and a JSON API — each page shows the code behind it.

  • 🔌 One trait — add HasFilters and a filters() method to a model. That's the setup.
  • 🪞 Self-describing — the server tells the frontend which columns exist, which operators each allows, their labels and how many values they take. That's what makes a generic panel possible.
  • 🎛️ Four frontends, one backend — no duplicated filter logic between them.
  • 🧩 Extensible — add your own filter types (with their own input views) and your own operators, without forking a shipped view.
  • 🎨 CSS-framework-agnostic — semantic markup, stable af-* classes, a bundled vanilla theme, and an opt-in Tailwind one.
  • 🔒 Safe by construction — filters() is the allow-list. Undeclared columns and disallowed operators are dropped before they reach SQL.

Installation

composer require laratribe/laravel-advanced-filters

The service provider auto-registers and the PHP side works immediately. For the shipped UI, see frontend assets.

Requires PHP 8.2+ and Laravel 10, 11, 12 or 13. Livewire 3/4 and Alpine are optional.

Quick start

1. Declare filters on the model

use Laratribe\AdvancedFilters\Concerns\HasFilters;
use Laratribe\AdvancedFilters\Contracts\Filterable;
use Laratribe\AdvancedFilters\Filters\{TextFilter, SetFilter, NumericFilter, DateFilter};

class Product extends Model implements Filterable
{
    use HasFilters;

    public static function filters(): array
    {
        return [
            TextFilter::make('name', 'Name'),
            SetFilter::make('category', 'Category')->options([
                'electronics' => 'Electronics',
                'books' => 'Books',
            ])->multiple(),
            NumericFilter::make('price', 'Price'),
            DateFilter::make('released_at', 'Released'),
        ];
    }
}

2. Filter and paginate

$filters = Product::normalizeFilters($request->input('column_filters'));

$products = Product::query()
    ->where('active', true)        // your own constraints
    ->applyFilters($filters)        // the trait scope
    ->paginate(25)
    ->withQueryString();

return view('products.index', [
    'products'      => $products,
    'filterFields'  => Product::filterDefinitions(),
    'activeFilters' => $filters,
]);

3. Render it

<x-advanced-filters::panel
    :fields="$filterFields"
    :active="$activeFilters"
    :base-url="route('products.index')"
/>

That's a working filter UI. See the docs for Livewire, Inertia and JSON API.

Filter types

Type Class Default operators
Text TextFilter contains, not_contains, starts_with, ends_with, equals, not_equals
Number NumericFilter equals, not_equals, >, <, ≥, ≤, between
Date DateFilter equals, >, <, between
Set SetFilter equals, not_equals, in, not_in

Plus your own, and your own operators.

The wire contract

Two plain-array shapes, no framework coupling, SemVer-stable:

  • Out — [{ key, label, type, input, clauses, clauseItems, optionItems? }]
  • In — [{ field, operator, value, valueTo? }]

Details.

Playground

A Testbench app demonstrating every frontend against a seeded SQLite model, including a custom filter type and a custom operator:

composer install
vendor/bin/testbench workbench:build
vendor/bin/testbench serve
# / → Blade + Alpine    /livewire → Livewire

Testing

composer test     # Pest
composer lint     # Pint
composer analyse  # PHPStan

Security

NumericFilter::havingExpression() accepts raw SQL and is developer-supplied, never user input — values are always bound as parameters. If you find a security issue, please email rns6393@gmail.com rather than opening a public issue.

👤 Author

Ram Sharma

If you find this package useful, please consider starring the repository on GitHub!

📜 License & Open Source

Laravel Advanced Filters is open-source software licensed under the MIT license.

You are completely free to use, modify and distribute this package in both personal and commercial projects. Contributions, issues and feature requests are always welcome — have a look at the issues page if you'd like to contribute.

Related Packages

laravilt/query-builder

Complete query builder system with filters, sorting, search, and pagination. Bui...

871 0
power-components/turbine

Headless, UI-agnostic table engine for Laravel: describe the grid in PHP, get JS...

1,295 1
salioudiabate/livewire-datatable

A professional, multi-datasource Livewire DataTable for Laravel — Eloquent, Quer...

16 0
manggala/laravel-manifest

Production-ready, schema-driven, UI-agnostic configuration platform for Laravel...

1 0
leenuxus/jarenui

A Jaren-UI compatible Livewire component library for Laravel — 50+ components, d...

13 0