PHPackages                             abather/table-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. abather/table-filters

ActiveLibrary

abather/table-filters
=====================

table filters

00PHP

Since Apr 6Pushed yesterdayCompare

[ Source](https://github.com/Abather/table-filters)[ Packagist](https://packagist.org/packages/abather/table-filters)[ RSS](/packages/abather-table-filters/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

[![Table Filters Banner](table-filters-banner.jpg)](table-filters-banner.jpg)

[![Latest Version on Packagist](https://camo.githubusercontent.com/3381040ddebcb5f6fbc19493ab4c0dbdacc7ae200751481cb4b344a69ccbdd08/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616261746865722f7461626c652d66696c746572732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/abather/table-filters)[![Total Downloads](https://camo.githubusercontent.com/627e9618dedfc22853e01a5346d28ee7e86da663808c306e9d4a91feb4268c17/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f616261746865722f7461626c652d66696c746572732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/abather/table-filters)

Table Filters
=============

[](#table-filters)

A fluent builder for [Filament](https://filamentphp.com/) table filters. Reduces repetitive filter boilerplate into a single chainable call.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Filament 4.x or 5.x

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

[](#installation)

```
composer require abather/table-filters
```

Usage
-----

[](#usage)

### Fluent builder (chained)

[](#fluent-builder-chained)

Use `TableFilters::make(ResourceClass::class)` inside your Filament resource's `table()` method and spread the result into `filters()`.

```
use Abather\TableFilters\Tables\Filters\TableFilters;

public static function table(Table $table): Table
{
    return $table
        ->filters(
            TableFilters::make(static::class)
                ->date()
                ->numeric('price')
                ->select('status')
                ->toggle('is_active')
                ->relation('category', 'name')
                ->filters(),
        );
}
```

### Standalone (individual filters)

[](#standalone-individual-filters)

Each filter is also available as a static method that returns a plain Filament `Filter` (or `SelectFilter`) component — the same object you would get from `Filter::make()` directly. This means you can chain any method from the [Filament filter documentation](https://filamentphp.com/docs/tables/filters) on top of it, such as `->label()`, `->hidden()`, `->columnSpan()`, `->default()`, and so on.

```
use Abather\TableFilters\Tables\Filters\TableFilters;

public static function table(Table $table): Table
{
    return $table
        ->filters([
            // returned as-is
            TableFilters::dateFilter('created_at', 'Created'),

            // chain any Filament filter method on top
            TableFilters::numericFilter('price', 'Price')
                ->columnSpan(2)
                ->hidden(fn () => ! auth()->user()->can('filter-prices')),

            TableFilters::selectFilter(static::class, 'status', 'Status')
                ->label('Order Status')
                ->default('active'),

            TableFilters::toggleFilter('is_active', 'Active'),
            TableFilters::relationFilter('category', 'name'),
            TableFilters::relationDateFilter('orders', 'created_at', 'Order Date'),
            TableFilters::relationNumericFilter('orders', 'total', 'Order Total'),
        ]);
}
```

> **Note:** `selectFilter()` requires the resource class as its first argument because it fetches distinct values from the database automatically.

Available Filters
-----------------

[](#available-filters)

### `date()` / `dateFilter()`

[](#date--datefilter)

Adds a date range filter (or a single date picker).

```
// chained
->date(
    field: 'created_at',   // column to filter on (default: 'created_at')
    label: null,           // optional label
    range: true,           // true → from/to pickers, false → single picker
    with_time: false,      // use DateTimePicker instead of DatePicker
)

// standalone
TableFilters::dateFilter(field: 'created_at', label: null, range: true, with_time: false)
```

---

### `numeric()` / `numericFilter()`

[](#numeric--numericfilter)

Adds a numeric range filter (or an exact-value filter).

```
// chained
->numeric(
    field: 'price',
    label: null,
    range: true,   // true → from/to inputs, false → single input
)

// standalone
TableFilters::numericFilter(field: 'price', label: null, range: true)
```

---

### `select()` / `selectFilter()`

[](#select--selectfilter)

Adds a select/dropdown filter. When no options are provided, distinct values are pulled from the database automatically.

```
// chained
->select(
    field: 'status',
    label: null,
    options: null,   // array, enum class-string, or null (auto-detect from DB)
    multiple: false,
    limit: 10,       // max distinct values fetched when options is null
)

// standalone — resource class is required as the first argument
TableFilters::selectFilter(resource: static::class, field: 'status', label: null, options: null, multiple: false, limit: 10)
```

---

### `toggle()` / `toggleFilter()`

[](#toggle--togglefilter)

Adds a boolean toggle filter.

```
// chained
->toggle(
    field: 'is_active',
    label: null,
    default: false,   // whether the toggle is on by default
    negation: false,  // when true, filters for false values instead of true
)

// standalone
TableFilters::toggleFilter(field: 'is_active', label: null, default: false, negation: false)
```

---

### `relation()` / `relationFilter()`

[](#relation--relationfilter)

Adds a select filter scoped to a relationship.

```
// chained
->relation(
    relationship: 'category',
    field: 'name',
    label: null,
    query: null,        // optional Closure to modify the relationship query
    searchable: true,
    preload: false,
    multiple: false,
)

// standalone
TableFilters::relationFilter(relationship: 'category', field: 'name', label: null, query: null, searchable: true, preload: false, multiple: false)
```

---

### `relationDate()` / `relationDateFilter()`

[](#relationdate--relationdatefilter)

Adds a date filter scoped to a relationship.

```
// chained
->relationDate(
    relationship: 'orders',
    field: 'created_at',
    label: null,
    range: true,
    with_time: false,
)

// standalone
TableFilters::relationDateFilter(relationship: 'orders', field: 'created_at', label: null, range: true, with_time: false)
```

---

### `relationNumeric()` / `relationNumericFilter()`

[](#relationnumeric--relationnumericfilter)

Adds a numeric filter scoped to a relationship.

```
// chained
->relationNumeric(
    relationship: 'orders',
    field: 'total',
    label: null,
    range: true,
)

// standalone
TableFilters::relationNumericFilter(relationship: 'orders', field: 'total', label: null, range: true)
```

Chaining
--------

[](#chaining)

All methods return `static`, so you can chain as many filters as needed:

```
TableFilters::make(static::class)
    ->date()
    ->date('updated_at', 'Updated', range: false)
    ->numeric('amount', 'Amount', range: false)
    ->select('status', 'Status', ['draft' => 'Draft', 'published' => 'Published'])
    ->toggle('featured')
    ->relation('author', 'name', searchable: true, preload: true)
    ->relationDate('orders', 'created_at', 'Order Date')
    ->relationNumeric('orders', 'total', 'Order Total')
    ->filters()
```

License
-------

[](#license)

MIT

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/2d032b178010eeffd089ecd6f75934079dc36d2d41328827f1d19c729572cbeb?d=identicon)[Abather](/maintainers/Abather)

---

Top Contributors

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

### Embed Badge

![Health badge](/badges/abather-table-filters/health.svg)

```
[![Health](https://phpackages.com/badges/abather-table-filters/health.svg)](https://phpackages.com/packages/abather-table-filters)
```

PHPackages © 2026

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