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

Nova Global Filter Laravel Package

marshmallow/nova-global-filter

A Laravel Nova package that adds global filters across your admin resources, letting you apply consistent filter criteria throughout the Nova dashboard. Configure filters once and reuse them everywhere for faster, more focused browsing of your data.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register

composer require marshmallow/nova-global-filter

Laravel package discovery should register the service provider automatically. Verify it appears in bootstrap/providers.php (Laravel 11+) or config/app.php, and check for a publishable config:

php artisan vendor:publish --provider="Marshmallow\\NovaGlobalFilter\\NovaGlobalFilterServiceProvider"

Because this package has essentially no adoption yet, treat the first install as a source-reading exercise, not a black-box dependency. Confirm the laravel/nova constraint in its composer.json matches your Nova major version before you build anything on it.

Where to look first

  1. README.md — the only reliable statement of the public API.
  2. src/ — the service provider, any facade, and the class that resolves filter values.
  3. config/ — how filters are mapped to cards/metrics.
  4. Any .vue files — if a card needs to read filter state client-side, the package likely ships a mixin or component.
  5. tests/ — often the clearest executable example of intended usage.

First use case

The canonical scenario: you already have a DateRange (or Status) filter on App\Nova\Order, and you want a "Revenue" value metric on a dashboard to respect the same filter. Instead of duplicating the filter logic inside the metric, register the existing filter with this package and read its resolved value in calculate():

// app/Nova/Metrics/Revenue.php
public function calculate(NovaRequest $request)
{
    $range = GlobalFilter::get('date_range'); // confirm exact accessor in README

    return $this->sum($request->model(), 'total', 'created_at')
        ->whereBetween('created_at', $range->toArray());
}

If that works, the package is worth keeping. If not, you've lost an afternoon and learned the source — acceptable for a zero-star dependency.

Implementation Patterns

Broadcast once, consume everywhere. Define the filter class on the resource as you normally would, then register that same class with the package rather than re-declaring options in each card. This keeps filter semantics in one place and means a change to the filter automatically reaches every metric and card.

Metrics: read, validate, scope. Inside calculate(), pull the filter values, normalize them (arrays vs scalars, nulls, defaults), then apply them to the query builder. Keep the normalization in a small helper or a custom filter class so multiple metrics don't repeat it.

Custom cards: pass state via meta. For a Vue card, resolve the filter server-side and expose it through withMeta() or the card's jsonSerialize() so the front end doesn't have to guess what the current filter is:

public function withMeta(): array
{
    return ['filters' => GlobalFilter::all()];
}

Then read this.card.filters in the component and include it in any follow-up AJAX request.

Dashboard workflows. If several cards on one dashboard should share a filter, register the filter at the dashboard level and ensure each card consumes the same key. This is the pattern that justifies the package's existence — otherwise you're just writing a query string.

Cache keys must include filter state. Nova metrics cache aggressively (cacheFor). Any metric with a filter-aware query must incorporate the filter values into the cache key, or you'll serve unfiltered results to a filtered request:

$this->cacheFor(now()->addMinutes(5))
    ->cacheKey(fn () => 'revenue-' . md5(json_encode(GlobalFilter::all())));

Integration tips

  • Keep the filter's apply() logic authoritative; when the package exposes the underlying filter instance, prefer calling its methods over re-implementing the query.
  • Register filters in NovaServiceProvider::filters() exactly as you would for a resource; the package should reuse, not replace, that mechanism.
  • If the package supports multiple resources, namespace filter keys (orders.date_range vs users.date_range) to avoid collisions.
  • Prefer server-side resolution over client-side: it keeps calculate() simple and avoids leaking filter definitions into JS.

Gotchas and Tips

Zero adoption means zero safety net. Pin an exact version ("marshmallow/nova-global-filter": "1.0.0"), commit the lockfile, and be prepared to fork. Check the commit history and issue tracker — a package last released recently but with no users often has an API that hasn't been battle-tested against Nova edge cases.

Filter state is request-scoped, and cards are separate requests. A metric card is loaded via its own AJAX call, which may not carry the resource index's ?filters= query string. The package's whole value proposition is bridging that gap — verify how it does so (session, cache, or a broadcast event) and test it after a hard refresh, not just after clicking the filter.

Defaults and nulls are the classic bug. A filter that hasn't been applied may return null, an empty array, or the filter's default depending on Nova version. Normalize once and log the raw value during development; don't assume a consistent shape.

Name collisions across resources. Nova filter keys are derived from the filter class name or uriKey(). Two DateRange filters on two resources will collide if the package keys only on the class. Alias them.

Cache poisoning. As above — a metric cached without filter state will happily serve one user's filtered result to another. Always include filter values in the cache key, and consider disabling metric caching entirely until you trust the implementation.

Validate before querying. Filter values arrive from the request. Cast dates, whitelist status enums, and use query bindings. Never interpolate a filter value into raw SQL, even if the package claims to sanitize it.

Debugging checklist

  1. Dump the request payload in calculate(); confirm the filter value is actually present.
  2. Inspect the network tab on the dashboard — is the card request carrying filter state?
  3. Check the package's service provider is registered and not silently failing to boot.
  4. Read the Vue component: does it re-fetch on filter change, or only on mount?
  5. Compare against a plain Nova metric with no filter to isolate whether the issue is filtering or the metric itself.

Extension points worth knowing. Most packages of this kind expose a resolver or mapping config so you can point a card at a filter that isn't registered on a resource. If the config file allows class-name overrides, use that rather than subclassing — it survives upgrades. If it ships a Vue mixin, prefer it over copying logic into each card component.

When to drop it. If you find yourself re-implementing filter resolution in every metric, or if the package doesn't support your Nova version cleanly, the fallback is straightforward: read request()->input('filters'), decode it, and apply it yourself in a shared trait. That's 30 lines and zero dependency risk.

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