PHPackages                             polysource/easyadmin-filter-bridge - 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. [Admin Panels](/categories/admin)
4. /
5. polysource/easyadmin-filter-bridge

ActiveSymfony-bundle[Admin Panels](/categories/admin)

polysource/easyadmin-filter-bridge
==================================

Polysource — drop-in package that enriches EasyAdmin v5 filters (ranges, multi-select, custom filter types, session persistence, chips) without forking EasyAdmin.

v0.9.0(2mo ago)0121MITPHP &gt;=8.1

Since May 9Compare

[ Source](https://github.com/polysource/easyadmin-filter-bridge)[ Packagist](https://packagist.org/packages/polysource/easyadmin-filter-bridge)[ Docs](https://github.com/polysource/polysource)[ RSS](/packages/polysource-easyadmin-filter-bridge/feed)WikiDiscussions Synced 3w ago

READMEChangelogDependencies (18)Versions (26)Used By (0)

polysource/easyadmin-filter-bridge
==================================

[](#polysourceeasyadmin-filter-bridge)

> Drop-in package that **enriches the filters of an existing EasyAdmin v5 app** without forking EasyAdmin. Plugs into EasyAdmin's `FilterConfiguratorInterface` extension point.

Status
------

[](#status)

**v0.5.7 published (2026-05-15).** API release-candidate stable — committed for v0.5.x, breaking changes allowed before v1.0 (cf. [ADR-012](../../docs/adr/0012-dual-product-positioning.md)). Distributed on Packagist as [`polysource/easyadmin-filter-bridge`](https://packagist.org/packages/polysource/easyadmin-filter-bridge).

Feature-complete on the bridge side, dogfooded on multi-tenant client integrations through v0.5.7:

- **All 8 built-in EasyAdmin filters covered** by an Enhancer (`DateTime`, `Boolean`, `Text`, `Numeric`, `Choice`, `Comparison`, `Array`, `Entity`).
- **4 custom filter types**: `BetweenDateFilter`, `InFilter`, `NotNullFilter`, `FullTextSearchFilter`.
- **Twig templates auto-register** via `PrependExtensionInterface` — enhanced widget HTML renders with zero config.
- **Filter session persistence** via `FilterSessionPersistenceSubscriber`on `BeforeCrudActionEvent` — operators returning to the index page see their previous filters restored automatically (scoped per CRUD controller FQCN, no leak across resources).
- **8 polysource routes auto-import** via `Bundle::boot()` since v0.5.4 — no manual `routes.yaml` import needed in the host.
- **Multi-kernel safe** since v0.5.7 — bundle is a no-op on EA-less kernels.
- **Multi-tenant ready** since v0.5.7 — opt out of auto-route registration via `auto_register_routes: false` to mount under a custom prefix (e.g. `/{channel}/admin`).

What it does
------------

[](#what-it-does)

Once installed, EasyAdmin's built-in filters gain richer form types, **without any change to your existing CRUD controllers**:

Built-in filterEnhancement`DateTimeFilter`Dedicated block prefix (`polysource_enhanced_datetime_filter`) + `presets` (today / last 7 days / …) + `show_clear` button.`BooleanFilter`Optional `include_null` flag — adds a third "Empty / Null" choice to filter rows where the column is `NULL`.`TextFilter`Optional `min_length` flag — skip filter for input shorter than the threshold (default 0 = no threshold).`NumericFilter``step` option (granularity hint, e.g. `0.01` for currency) + `quick_ranges` buttons.`ChoiceFilter``inline` option — render choices as pills/badges instead of dropdown.`ComparisonFilter``comparisons` option — whitelist of operators to expose in the dropdown (default `[]` = all).`ArrayFilter``chip_display` option — selected items as removable chips instead of multi-line list.`EntityFilter``placeholder` option — custom placeholder text for the dropdown / autocomplete.Plus, list-level capabilities layered on top:

- Filter **chips/tags** bar above the table (active filters visible, click X to remove).
- **Session persistence** of filters per CRUD controller FQCN.
- **Saved views** dropdown (private / team / public scopes).
- **Column visibility** dropdown + **column reordering**.
- **Filter-aware streaming export** (CSV / XLSX).
- **Matching-count** JSON endpoint for bulk dry-run preview.
- **Filter URL tokens** for short shareable filtered URLs.
- Custom filter types: `BetweenDateFilter`, `InFilter`, `NotNullFilter`, `FullTextSearchFilter`.

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

[](#installation)

```
composer require polysource/easyadmin-filter-bridge
```

The bundle auto-registers via Symfony Flex. If you don't use Flex, add it manually to `config/bundles.php`:

```
return [
    // …
    Polysource\EasyAdminFilterBridge\PolysourceEasyAdminFilterBridgeBundle::class => ['all' => true],
];
```

**Zero configuration needed.** As soon as the bundle is loaded, the shipped Configurators auto-tag themselves via EasyAdmin's `registerForAutoconfiguration(FilterConfiguratorInterface::class)`, and EasyAdmin's `FilterFactory` picks them up to mutate filter DTOs right after they are created.

### Frontend assets (filter modal tabs / chips / saved-views)

[](#frontend-assets-filter-modal-tabs--chips--saved-views)

The richer modal layout (tabs + accordions for dozens of filters) and the chips bar above the table are powered by Stimulus controllers shipped under `assets/controllers/`. EasyAdmin auto-loads them when the bundle is autoconfigured **only** if your host app uses [Symfony AssetMapper](https://symfony.com/doc/current/frontend/asset_mapper.html)or Webpack Encore + StimulusBundle.

If the modal opens flat (no tabs, all filters stacked) or the chips do not appear, your host is most likely missing the AssetMapper wiring. Two-step fix:

1. Make sure `symfony/asset-mapper` and `symfony/stimulus-bundle` are installed and `framework.yaml` enables both.
2. In your `assets/bootstrap.js` (or `app.js`), confirm the auto-load line is present:

```
import { startStimulusApp } from '@symfony/stimulus-bundle';

const app = startStimulusApp();
// no manual import needed — Stimulus auto-loads
// vendor/polysource/easyadmin-filter-bridge/assets/controllers/*.js
```

3. Then make sure EasyAdmin pages include your importmap. EasyAdmin uses its own bundled assets by default and ignores the host importmap, so add it back via your Dashboard:

```
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;

final class DashboardController extends AbstractDashboardController
{
    public function configureAssets(): Assets
    {
        return Assets::new()->addAssetMapperEntry('app');
    }
}
```

Without this last step the Stimulus controllers ship in the bundle but never boot on EasyAdmin pages — the modal stays flat.

### Saved views (POST routes)

[](#saved-views-post-routes)

`polysource/filter` ships a saved-views feature (dropdown, save, load, delete). The bridge wires the create / delete routes for EasyAdmin out of the box — they live at:

- `POST /admin/saved-views` (`polysource_saved_view_create`)
- `POST /admin/saved-views/{id}/delete` (`polysource_saved_view_delete`)

To enable them, add the bridge controller directory to your `config/routes.yaml`:

```
polysource_easyadmin_filter_bridge:
    resource: '../vendor/polysource/easyadmin-filter-bridge/src/Controller/'
    type: attribute
```

A `BeforeCrudActionEvent` subscriber also expands `?view=` into the EA `filters[...]=...` query and redirects to a clean URL — no host code needed.

Quick start
-----------

[](#quick-start)

Take any existing EasyAdmin CRUD controller:

```
namespace App\Controller\Admin;

use App\Entity\Product;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Filter\DateTimeFilter;
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;

final class ProductCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return Product::class;
    }

    public function configureFilters(Filters $filters): Filters
    {
        return $filters
            ->add(DateTimeFilter::new('createdAt'))
            ->add(BooleanFilter::new('isActive'));
    }
}
```

After installing this bridge, **the same code** automatically:

- The `createdAt` filter renders with the enhanced datetime form type (dedicated block prefix for theme overrides) instead of the stock date picker.
- The `isActive` filter accepts an `include_null` option (default `false`) to show a third "Null" radio choice when the column is nullable.

To opt-in to per-resource overrides, pass `formTypeOptions` to the upstream filter:

```
->add(BooleanFilter::new('archivedAt')->setFormTypeOption('include_null', true))
```

How the seam works
------------------

[](#how-the-seam-works)

```
┌───────────────────────────────────────────────────────┐
│ EasyAdmin's FilterFactory::create()                   │
│                                                       │
│   foreach ($filterConfig as $filter) {                │
│     $filter = DateTimeFilter::new('createdAt')        │
│                  ->setFormType(DateTimeFilterType)    │  ← stock setup
│     $filterDto = $filter->getAsDto();                 │
│                                                       │
│     foreach ($this->filterConfigurators as $cfg) {    │  ← OUR HOOK
│       if (!$cfg->supports($filterDto, …)) continue;   │
│       $cfg->configure($filterDto, …);                 │  ← we mutate the DTO
│     }                                                 │
│   }                                                   │
└───────────────────────────────────────────────────────┘

```

**No EasyAdmin code is modified.** We only attach more services to the existing extension point.

The full audit trail of seams used (and one that is *not* available — the `EntityRepositoryInterface` returns `Doctrine\ORM\QueryBuilder`, which blocks non-Doctrine sources) is in [ADR-012 §Vérification technique](../../docs/adr/0012-dual-product-positioning.md#v%C3%A9rification-technique).

Writing your own enhancer
-------------------------

[](#writing-your-own-enhancer)

Want to add a custom Configurator (e.g. a richer `TextFilter` with mode-toggle "exact / starts-with / contains")? The pattern is small:

```
namespace App\Filter\Configurator;

use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Filter\FilterConfiguratorInterface;
use EasyCorp\Bundle\EasyAdminBundle\Dto\{EntityDto, FieldDto, FilterDto};
use EasyCorp\Bundle\EasyAdminBundle\Filter\TextFilter;

final class TextFilterModeEnhancer implements FilterConfiguratorInterface
{
    public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): bool
    {
        return TextFilter::class === $filterDto->getFqcn();
    }

    public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void
    {
        $filterDto->setFormType(MyTextFilterType::class);
        $filterDto->setFormTypeOptions(array_merge(
            $filterDto->getFormTypeOptions(),
            ['modes' => ['exact', 'starts_with', 'contains']],
        ));
    }
}
```

With Symfony's autowiring + autoconfiguration (default), it gets auto-tagged `ea.filter_configurator`. **Done.** No service.yaml entry, no compiler pass, no fork.

Testing
-------

[](#testing)

```
# from the monorepo root
make test
```

Unit tests live in `tests/Unit/Configurator/` — they instantiate real `FilterDto` instances (not mocks), run our `supports()` + `configure()`, and assert the DTO mutations. `EntityDto` and `AdminContext` are `final`in EasyAdmin v5, so the tests use `(new ReflectionClass(...))->newInstanceWithoutConstructor()` to satisfy the typehints without coupling to internal shape — the Configurators never read either argument.

Compatibility
-------------

[](#compatibility)

- **PHP** 8.4+ (will widen to 8.2+ in v0.5+)
- **Symfony** 7.4 LTS (will widen to 6.4+ in v0.5+)
- **EasyAdmin** `^4.24 || ^5.0`

Architectural decisions
-----------------------

[](#architectural-decisions)

- [ADR-012 — Dual-product positioning](../../docs/adr/0012-dual-product-positioning.md) — why this bridge exists alongside `polysource/admin` standalone.
- [ADR-016 — Bridge contracts shared with polysource/filter](../../docs/adr/0016-bridge-contracts-shared-with-polysource-filter.md) — the `ChipFormatterInterface` boundary between the bridge and the standalone primitive.

License
-------

[](#license)

MIT — see [LICENSE](../../LICENSE).

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance86

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

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

25

Last Release

68d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/41d53ab82016651b0a4a9ef71644a54f934d8bf54ccbc59fc0183f994213ef38?d=identicon)[samaym](/maintainers/samaym)

---

Tags

symfonyfilteradmineasyadminpolysource

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/polysource-easyadmin-filter-bridge/health.svg)

```
[![Health](https://phpackages.com/badges/polysource-easyadmin-filter-bridge/health.svg)](https://phpackages.com/packages/polysource-easyadmin-filter-bridge)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M400](/packages/easycorp-easyadmin-bundle)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1616.4k14](/packages/2lenet-crudit-bundle)[chameleon-system/chameleon-base

The Chameleon System core.

1028.7k5](/packages/chameleon-system-chameleon-base)

PHPackages © 2026

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