seoegypt/value-filter
A lightweight Laravel package for filtering incoming request values and query parameters. Apply clean, reusable filter rules to validate and sanitize data before it reaches your application logic, keeping controllers and services tidy.
Architecture fit. Low ceiling, narrow slot. This package occupies exactly one seam in a Laravel application: the filters() method of a Nova Resource, where it shapes the Eloquent query behind an admin index screen. It is not a sanitization or validation layer for application code, despite what its own description advertises. The first TPM action is to correct that framing with stakeholders — "filter, normalize, and transform values" reads like an input-validation library, and if anyone scopes work against that description, the estimate and the design are both wrong. Realistic architectural fit: internal admin tooling only, for discrete-value equality filtering (order status, user role, ticket priority, moderation state), in an org that already runs Nova.
Integration feasibility. Mechanically trivial, procedurally gated. Integration is a use statement plus one array entry per Resource — hours of work, not days. The gates are environmental, not technical:
auth.json credentials. Without it, composer require fails with a Nova authentication error that never mentions value-filter, which misroutes the debugging effort.composer.lock inherits that credential requirement.key(), name(), and apply() semantics must be read from src/ before writing any code. There is no blog trail, no issue-thread lore, no dependents — 3 stars and 0 dependents means the burden of understanding is fully ours.Technical risk. Four distinct risks, in priority order:
composer.json, the PHP floor). A stale Composer constraint can block an unrelated security upgrade months later, discovered at the worst possible moment.Key questions.
Stack fit. Laravel + Nova only, and only for admin-facing index filtering. It has no role in form requests, jobs, service classes, API input validation, or anything customer-facing. The pragmatic default posture is the vendor path: copy the filter class (and the Vue component, if shipped) into app/Nova/Filters and resources/js/nova, delete the Composer dependency, and own roughly fifty lines forever. That decision is cheap now and expensive to defer. Treat the package as a reference implementation or scaffold, not a vendor relationship — which is to say the internal framing is "we own this code," and the ticket should be written that way.
Migration path. Two viable routes, chosen up front:
--with-all-dependencies, register on exactly one low-traffic Resource first. Document the pinned version and its constraints in the upgrade runbook the same day.apply() for query semantics and tenant scoping, options() for a fixed input set instead of free text, key()/$name for identity and per-Resource labels, canSee() for visibility, default() for the preselected value.Extension points in order of usefulness: apply(), options(), key()/$name, canSee(), default(). The Vue component is last resort — touch it only after vendoring.
Compatibility. Validate three things against the current lockfile before committing to any estimate: Nova major version, the Laravel constraint in the package's composer.json, and the PHP floor. Do not assume a 2023 filter works on a 2025 Nova panel. Pin exactly and disable automated update PRs — an unreviewed patch bump can break the admin panel silently, and the breakage will present as a wrong list, not an error.
Sequencing.
src/ and document actual behavior: FQCN, key(), name(), apply() handling of null, arrays, and unexpected types. Half a day.filters payload; assert expected IDs present and excluded IDs absent; explicit cases for null, unknown value, wrong type). Run it against production-shaped data, not a three-row seed.EXPLAIN on the target column at production scale.Do not skip step 5 to save a day. It is the only mitigation for the silent-failure mode.
Maintenance. Full ownership, immediately and permanently, regardless of which integration path is chosen. The dependency path only delays that reality and adds a Composer constraint to the upgrade runbook in the meantime. Budget realistically: the code is ~50 lines and stable; the overhead is not the code, it's the Nova major upgrade cycle, where every filter gets re-validated. Assign a named owner, add the filter to the Nova upgrade checklist, and document its intended semantics in the repo so the next engineer isn't reverse-engineering apply() from scratch.
Support. Upstream support is effectively zero. No maintainer, no dependents, no issue history to mine. Any defect, regression, or compatibility break is ours to diagnose and fix. This is acceptable for a fifty-line admin filter and unacceptable for anything with an SLA — which is precisely why scope stays internal. A related support cost on the dependency path: every pipeline that resolves the lockfile needs Nova credentials, and failures surface as opaque Composer errors.
Scaling. Query scaling, not load scaling. The filter compiles to a where on the admin index query, executed on every page load for every operator. Low-cardinality indexed columns at tens of thousands of rows are comfortable; millions are not. Run EXPLAIN on production-shaped data before rollout and revisit if the table grows an order of magnitude. Feature scaling is capped: the moment the requirement moves past single-column equality — ranges, operators, tenant scoping, multi-column — the honest answer is to write the filter in-house. At that point this package's tiny surface becomes something we fight rather than reuse.
Failure modes.
tinker query for every option.null and type coercion — a bare where($column, null) compiles to is null, which may or may not be intended; array values behave differently than expected. Assert both explicitly.key() collision — the Nova base returns the class basename, so two instances of the same filter class on one panel clobber each other's state. Subclasses get a new key for free; registering the same class twice with different config requires explicit keys.Ramp-up. Low for anyone fluent in Nova. The real ramp-up cost is comprehension, not syntax: read src/, understand what apply() actually does, and verify behavior by hand before trusting it. Estimate half a day for a Nova-fluent engineer to audit and wire the first filter, plus half a day for the regression test and EXPLAIN check. Then treat the package as a reusable pattern — the leverage for a TPM is standardizing the approach (one owned filter class, tested as a query contract, registered via a shared base Resource) across the admin-tooling backlog, which turns a series of one-off "add a filter" tickets into a single auditable pattern. That is the actual product value here: not the package, but the repeatable shape it demonstrates.
Governance, stated once for the record: pin to a commit, disable automated updates, name an owner, add to the Nova upgrade checklist, require the regression test, and keep it off revenue-critical, SLA-backed, security-sensitive, or multi-tenant-critical surfaces. Internal admin tooling only.
How can I help you explore Laravel packages today?