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

Awesome Filter Bundle Laravel Package

netbull/awesome-filter-bundle

Netbull AwesomeFilterBundle is a Symfony bundle that adds reusable filter types for building flexible, query-driven filter forms. Simplify filtering logic in your admin panels and listings with configurable, ready-to-use filters that plug into your existing Symfony stack.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what you're installing first. netbull/awesome-filter-bundle is a Symfony bundle, not a Laravel package. There is no AwesomeFilterServiceProvider, no facade, no config/awesome-filter.php. Everything below assumes you are either (a) pulling framework-agnostic value classes out of it, or (b) writing a ~50-line bridge yourself.

composer require netbull/awesome-filter-bundle:^7.0

Current release is v7.0.1 (2025-06-12) — a patch that only clears a deprecation. Nothing in it changes the integration story below, but the version number itself is informative: this is the seventh major line of a package with zero dependents. Plan accordingly (see Gotchas).

Where to look, in order:

  1. src/ — the filter/value classes you'll actually touch. Read these before anything else; with 0 stars and 0 dependents, the source is the documentation.
  2. DependencyInjection/Configuration.php — the config tree is the single best inventory of every knob the bundle exposes. If a feature isn't a node here, it isn't configurable.
  3. Resources/config/services.* — shows which classes are registered as services and, critically, which constructor dependencies they demand (this is where Doctrine or Symfony Form coupling will bite you).
  4. composer.json — check for symfony/form, doctrine/orm, symfony/http-foundation. Any of those present means the package is not extractable in isolation without pulling a large chunk of the Symfony stack along. Also check the php and symfony/* version constraints: a v7 line almost certainly means PHP 8.2+ and Symfony 6/7 only.
  5. README / CHANGELOG — last, not first. With a project this small the changelog is a release log, not a usage guide.

First use case to target: a filterable index endpoint. GET /api/orders?status=paid&created_from=2025-01-01&sort=-total. The bundle's value proposition is representing that querystring as typed filter objects instead of a $request->only([...]) soup in the controller. Build exactly that one endpoint before considering a second.

If composer.json requires symfony/framework-bundle, stop and reconsider. You'll be installing a mini Symfony kernel inside Laravel to filter a query. In that case the honest recommendation is to read the package as design inspiration (how it models filters, how it maps request data to filter DTOs) and reimplement the ~200 lines that matter as app/Filters/. That is not a knock on the code — it's a dependency-graph reality.

If the core classes are framework-agnostic (plain PHP, no ContainerInterface in constructors), you're in luck: composer require, autoload works, and you skip the bundle registration entirely.

Implementation Patterns

Pattern 1 — Filter DTO per request, applied by an applier

The workable integration is a two-layer split. The bundle supplies (or inspires) the filter object; you own the translation to Eloquent.

// app/Filters/OrderFilter.php — a typed, validated representation of the querystring
final class OrderFilter
{
    public function __construct(
        public readonly ?string $status = null,
        public readonly ?string $createdFrom = null,
        public readonly string $sort = '-created_at',
    ) {}

    public static function fromRequest(Request $request): self
    {
        $data = $request->validate([
            'status'       => ['nullable', 'string', 'in:pending,paid,shipped'],
            'created_from' => ['nullable', 'date'],
            'sort'         => ['nullable', 'string', 'in:created_at,-created_at,total,-total'],
        ]);

        return new self(
            status: $data['status'] ?? null,
            createdFrom: $data['created_from'] ?? null,
            sort: $data['sort'] ?? '-created_at',
        );
    }
}

Then a single applier that owns all query mutation:

final class OrderFilterApplier
{
    public function apply(Builder $query, OrderFilter $filter): Builder
    {
        $query->when($filter->status, fn ($q, $v) => $q->where('status', $v));
        $query->when($filter->createdFrom, fn ($q, $v) => $q->where('created_at', '>=', $v));

        [$col, $dir] = str_starts_with($filter->sort, '-')
            ? [substr($filter->sort, 1), 'desc']
            : [$filter->sort, 'asc'];

        return $query->orderBy($col, $dir);
    }
}

If the bundle gives you a FilterInterface or an apply()/getQueryBuilder() contract, implement that contract in OrderFilterApplier so you get the bundle's composition features (chaining, collections) for free while Eloquent does the actual SQL. Check this contract against v7 specifically — after six prior majors it has very likely been renamed or re-signatured; don't code against signatures from a two-year-old blog post or the v2-era README.

Pattern 2 — Filter collections for admin grids

The pattern these bundles exist to serve: an array of independent filter objects, each conditionally contributing a WHERE, so a 14-column admin table doesn't become a 90-line controller method.

$filters = collect([$statusFilter, $dateRangeFilter, $searchFilter])
    ->filter(fn ($f) => $f->isActive());   // skip unset filters entirely

$filters->each(fn ($f) => $f->applyTo($query));

The isActive() guard is the important bit — it prevents where('status', null) from silently producing status IS NULL and returning an empty grid at 2am.

Pattern 3 — Bridge the Symfony container if you must

Only if the bundle genuinely requires it. Register the bundle's services manually in a service provider rather than booting a Symfony kernel:

public function register(): void
{
    $this->app->singleton(SomeBundleFilterFactory::class, function () {
        return new SomeBundleFilterFactory(/* hand-wire constructor deps */);
    });
}

Read Resources/config/services.* to get the constructor argument list right — that file is the ground truth, not the README. On a v7 line, expect autowiring aliases and PHP 8 attributes there rather than the explicit <argument> XML/YAML lists you'd see in v1-era bundles; the shape of that file changes across majors.

Pattern 4 — Test the filter contract, not the SQL

it('filters by status', function () {
    Order::factory()->create(['status' => 'paid']);
    Order::factory()->create(['status' => 'pending']);

    $filter = new OrderFilter(status: 'paid');
    $results = (new OrderFilterApplier)->apply(Order::query(), $filter)->get();

    expect($results)->toHaveCount(1);
});

Assert on the filter's behaviour, so if you later swap the bundle for a hand-rolled implementation the tests survive. This matters more than usual here: with seven majors behind it, the upstream API you're wrapping is demonstrably not stable, but your tests can be.

Pattern 5 — Keep it out of the controller

Route::get('/orders', function (Request $request, OrderFilterApplier $applier) {
    $filter = OrderFilter::fromRequest($request);
    return OrderResource::collection($applier->apply(Order::query(), $filter)->paginate());
});

One line in the route file. The moment filter logic leaks into controllers it duplicates, and with a package this small you have no upstream to fix the duplication for you.

Gotchas and Tips

AGPL-3.0 is the headline risk. This is a network-copyleft licence. If you deploy a Laravel app that links this package and expose it over a network, the AGPL's §13 obliges you to offer corresponding source to users. For most commercial SaaS this is a non-starter without legal sign-off. If you only want the ideas, read the MIT/BSD-licensed equivalents or write your own. Treat this as a blocking question, not a footnote. Re-verify the licence in composer.json for v7 — licences do change between majors, and this is the one fact worth confirming with your own eyes rather than inheriting from any assessment.

v7.0.1 tells you more than the changelog does. The release itself is trivial — one commit, "clear deprecation" — but the version is the signal. A package at major 7 with 0 dependents has churned its public API six times without an installed base to slow it down. That is the opposite of the stability guarantee a Laravel dev normally reads into a high major number (where ^7.0 on a popular package means "battle-tested and settled"). Here, treat the major as a churn counter, not a maturity badge. Pin exactly and read every diff.

The deprecation fix implies a modern, maintained stack — and a moving floor. Clearing deprecations almost always means aligning with a newer PHP or Symfony minor. Concretely: v7.0.1 likely targets PHP 8.2/8.3+ and Symfony 6.4/7.x, and the previous majors are effectively abandoned (the author will not be backporting that fix). Two consequences for you: (a) if your Laravel app is on an older PHP, v7 may not install at all — check composer.json require.php before you plan the work; (b) you cannot "just stay on v6" to dodge a problem, because v6 is now a dead branch. Budget for keeping pace, or don't take the dependency.

Zero stars, zero dependents, zero community. There will be no StackOverflow answers, no blog posts, no third-party tutorials — and now, no answers for v7 specifically, since any stray content you find will describe v1–v3 APIs. Every question is answered by reading src/. Budget for that. Correspondingly, the code is likely small enough to read in an afternoon — which is the saving grace.

Symfony bundle ≠ Laravel package. No auto-discovery, no php artisan vendor:publish (no publishable assets unless Resources/config ships them, and even then the config format is Symfony YAML/XSD, not Laravel's array config). config/packages/*.yaml examples in the docs are inert in a Laravel app.

Doctrine leakage. If src/ contains Doctrine\ORM\QueryBuilder typehints, you cannot reuse the filtering logic against Eloquent without an adapter. Check composer.json before writing a single line of integration code.

Symfony Form dependency. Some of these filter bundles build filters as Symfony Forms. If so, you inherit the entire Form component's validation/rendering model — which duplicates and fights Laravel's Validator and FormRequest. At that point the package is fighting your framework, and you should stop.

Release cadence vs. stability. Active maintenance is confirmed (a patch landed 2025-06-12, same day as the v7.0.0 tag — the author shipped and immediately cleaned up). That's a good sign for responsiveness and a bad sign for your calendar: majors have historically arrived fast enough that the deprecation fix was needed within hours of the major. Pin explicitly (composer require netbull/awesome-filter-bundle:^7.0), commit composer.lock, and read the diff before composer update. Never run a bare composer update in a project that depends on this.

Debugging: if a filter silently does nothing, the failure is almost always (a) the filter's isActive() returning false on a value you thought was set, or (b) the applier not being invoked because you called ->get() before ->apply(). Log the composed query with ->toSql() / ->dd() at the applier boundary — that single log line will resolve 80% of issues. On v7, add a third suspect: an API shape that changed since the docs you're reading, so confirm method names against src/ rather than memory.

Extension points to look for: a filter interface you can implement for custom types, a registry/collection you can push into from a service provider, and a config node for default behaviour. If none of those three exist, the package is a closed set of filter types — fine for reading, bad for extending.

Escape hatch, and my actual recommendation for most teams: if the integration cost exceeds an afternoon, lift the Filter DTO pattern into app/Filters/, delete the dependency, and sidestep AGPL entirely. You keep the architectural benefit, the package's design insight, and none of the licence, bundle-shimming, or major-version-churn risk. A one-commit patch release doesn't change that calculus — if anything, the fact that the package is on major 7 reinforces it.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource