Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filter Manager Bundle Laravel Package

smoked/filter-manager-bundle

A Symfony bundle for building configurable, reusable filters and applying them to Doctrine queries. Define filter sets, generate filter forms, and compose query criteria through a clean, service-based API for admin lists and search screens, with extensible filter types.

View on GitHub
Deep Wiki
Context7

Getting Started

The first thing to internalize: despite the description calling it "framework-agnostic core with simple integration," this ships as a Symfony bundle. In a Laravel app there is no auto-discovery, service provider, or publishable config. Your first step is not composer require — it is reading the source on GitHub.

Minimal steps

  1. Read composer.json before installing. Check require for symfony/*, php, and doctrine/* constraints, and check autoload.psr-4 to see the namespace split between the bundle wrapper (...\Bundle\...) and the framework-agnostic core (...\FilterManager\...). The bundle namespace is the part you ignore; the core is what you may reuse.
  2. Vendor the core, don't require the bundle. If the core namespace has no Symfony or Doctrine imports, copy those files into app/Support/FilterManager, keep the MIT header, and wire it yourself. Pin to a commit SHA rather than a floating constraint.
  3. First use case: a product listing with three static filters — status (equals), price (range), category (in). Define them once, compose them into a named set plp_default, and apply that set to an Eloquent builder. One day, feature-flagged.

Where to look first in the source

  • The registry/manager class — how filters are declared (array config, interface, attributes, hardcoded).
  • The filter contract/interface — the apply()/filter() signature and what it receives: a value object, a request, or a raw query builder. This single decision determines whether the package is adaptable or a dead end for you.
  • The filter set / composition class — how named sets are combined (AND vs OR) and whether sets are composable with each other.
  • Any DependencyInjection/ extension — confirms what the bundle adds on top and therefore what you can drop.

Realistic first wiring (verify names against source — the shape is what matters):

$registry = new FilterRegistry();
$registry->add('status',   new EqualsFilter('status'));
$registry->add('price',    new RangeFilter('price'));
$registry->add('category', new InFilter('category_id'));

$set = $registry->set('plp_default', ['status', 'price', 'category']);

$criteria = $set->fromRequest($request->query()); // or ->resolve($input)

$query = Product::query();
foreach ($criteria as $filter) {
    $filter->applyToEloquent($query); // adapter you write
}

The deliverable of "getting started" here is a time-boxed spike plus a short internal note — the filter registration model, the query-construction contract, and the gaps against your catalog schema. That note is more durable than the decision to adopt or not.

Implementation Patterns

Given the package's age and adoption, the patterns that matter are the ones that keep it swappable.

1. Wrap the package behind your own interface. No controller or model should touch package classes directly. Define a single seam and let the package be one implementation. This is the difference between a reversible experiment and a rewrite when the package rots.

interface ProductFilterResolver
{
    public function resolve(array $input): ProductFilterSet;
}

2. Adapter pattern for the query layer. The bundle's native habitat is Doctrine. For Eloquent, write a small adapter translating each filter into a where / whereBetween / whereIn closure. Keep the adapter dumb — no business logic lives there.

3. Named sets as configuration, not code. Define filter sets (plp_default, admin_search) in a config array or table, not scattered conditionals. This is the actual value proposition — centralization — and it survives even if you drop the package later.

4. Validate input at the boundary. Allowlist every filter name and value in your resolver before it reaches the package. Treat the package's input as untrusted; it almost certainly does not validate column names or sort keys.

5. Feature-flag the whole path. You get a clean rollback and a place to A/B against the from-scratch implementation you will probably end up writing anyway.

6. Characterization tests first. Before wiring it in, pin the observable behavior: given these inputs and this set, these records come back in this order. Those tests are your safety net when you replace the package.

Integration tips

  • Use it for read paths only. Do not let it participate in writes.
  • Keep the filter value object immutable and serializable — it becomes your contract for GET /products?filter[...] and for pagination/cursor interaction.
  • Log which filters were applied per request. Silent filter degradation is the failure mode you will actually hit.

Gotchas and Tips

  • The Symfony bundle wrapper is dead weight in Laravel. Don't try to boot it. *Bundle, DI extension, and service registration are irrelevant — extract the core or skip the package.

  • No auto-discovery, no service provider, no config publishing. You wire everything by hand and own the wiring.

  • Zero adoption means no known-issues map. There is no Stack Overflow answer, no issue thread, no example app. Your source reading is the documentation — write your own internal note after the spike, while it's fresh.

  • Query safety is unverified. A "filter manager" by definition turns user input into DB predicates. Assume column names and sort keys are interpolated unless you see an allowlist. Never pass raw request keys through.

  • No release cadence. Do not take a floating ^1.0 constraint. Pin to a SHA if you vendor it at all, and keep the source under version control in your repo so upstream changes remain mergeable if it revives.

  • Version rot. Check PHP and symfony/* constraints against your runtime. If it predates PHP 8 typed properties or uses ContainerAware, budget for patching the core — which further erodes the "just install it" value.

  • Testing is your responsibility. Assume no upstream suite. Your characterization tests are the only tests.

  • N+1 and facets. If filters touch relations (variants, attribute values), watch for N+1. If you need filter-value counts, this package will not give them — plan for a search engine or a separate aggregation query.

  • The failure mode to grep for is silent no-ops. Add an assertion that a non-empty filter set actually produced a WHERE clause, or log a warning when a registered filter resolves to nothing. A filter that quietly stops applying after a schema change returns unfiltered results and users may not notice.

  • The one extension point that matters is the filter contract. If it takes a query builder, it is opinionated and hard to swap; if it returns a value object, you can adapt it to Eloquent, Doctrine, or a search backend. Determine which before committing.

  • Don't gate roadmap on it. Zero stars, zero dependents, no maintainer signal — treat it as a read-only design reference, not a dependency. Under an SCA/compliance process it is more likely to be flagged than approved.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console