occ-therapist/form-request-validation-for-filament
Reuse Laravel Form Requests inside Filament: attach one to a schema or table filter and its rules, messages, and attributes apply automatically to matching fields, with wildcard mapping, context-aware per-page rules, and smart rule merging.
Single source of truth for validation (build vs. buy vs. duplicate). The package lets a Filament admin panel reuse existing Laravel Form Requests instead of re-declaring rules as ->required() / ->email() chains on every field. The decision it informs: do we duplicate validation across API and admin UI, or invest in one reusable layer? Today most teams pick duplication by default because it's free; this package makes the "single source" option cheap enough to consider.
Admin-surface scope and speed. It directly de-risks delivery of admin/back-office features where the same entity is edited through both an API and a Filament panel (users, posts, orders, tenant settings). That's a velocity lever on internal tooling — typically the lowest-glamour, highest-volume roadmap item — rather than a customer-facing feature.
Roadmap sequencing for admin parity. Because it covers resource create/edit, action modals, wizards (per-step), relation managers, and table filters, it supports a product decision like "ship parity between API validation and admin validation in one release, not two." The table-filter support (v1.2.0) specifically unblocks self-serve reporting/filtering features where bad filter input currently fails silently or produces empty states.
Framework-version commitment. Supporting Filament 4.x and 5.x via a single internal adapter is a real signal: adopting it slightly lowers the cost of an eventual Filament major upgrade, and it narrows the "we can't upgrade because of plugin lock-in" risk that PMs get asked to accept. Requires Laravel 12/13 — so it also encodes a decision to be off Laravel 11 (now EOL, blocked by Composer security advisories).
Context-aware UX rules. Different Form Requests per page (create vs. edit) means product rules like "email unique only on create" and "password required only on edit" are expressible without forking field definitions — a small but recurring source of admin bugs.
What it explicitly does not decide for you. authorize(), withValidator(), passedValidation()/failedValidation() are unsupported; authorization stays in Filament policies. Don't let this package be sold internally as a validation or security consolidation — it's rules, messages, and attribute labels only. Note the README's limitations table appears stale versus the v1.3.0 release notes, which claim prepareForValidation() support; verify before relying on it.
Risk-adjusted verdict. 5 stars, 0 dependents, one maintainer, first releases within a very short window, "readme + releases" maturity. This is a convenience dependency in a non-customer-facing layer, not a platform bet. The product decision it best supports is a time-boxed pilot on one resource, not org-wide standardization.
Consider it when:
items.*.name) or dot-notation filter rules without writing per-field glue.->formRequest() call than maintain a custom trait that re-implements state-path normalization (data.email, mountedActions.0.data.email, tableDeferredFilters.created.from) — that normalization is the genuinely fiddly part, and it's the most defensible reason to buy rather than build.Look elsewhere (or build ~40 lines in-house) when:
authorize(), withValidator(), or post-validation hooks — these are out of scope, so you'd be adopting a dependency that covers only part of your existing base class. That mismatch is the most common reason this package disappoints.->required()->email() approach is genuinely fine and the abstraction isn't earned.Adoption guardrails if you proceed: pin the version, read the source before first use (it's small), write a regression test per Filament surface you attach it to, subscribe to releases, and keep a fork-ready posture (MIT, so forking is permitted). Treat the "call ->formRequest() after ->components()" ordering requirement as a documented footgun to lint or code-review for, since silent non-application is the failure mode.
For executives — the one-paragraph version: "Our API and our admin panel validate the same data twice, with two sets of rules that drift apart. This small open-source library lets the admin panel reuse the validation rules we already wrote, so a rule changes in one place. It's a maintenance-cost reduction on internal tooling, not a customer-facing capability — no new revenue, but fewer admin data-quality bugs and faster back-office delivery. It's free (MIT), low-blast-radius, and we propose a one-sprint pilot on a single screen before deciding. Main caveat: it's a young, single-maintainer project, so we'd pin the version and accept owning a fork if it goes stale."
For engineering — be direct: "Schema::formRequest() / Table::filtersFormRequest() map Form Request rules onto matching fields by name, dot notation, and wildcards, with state-path normalization for resource pages, action modals, wizards, and deferred vs. live table filters. Rules merge with existing field rules, Form Request wins on conflicts, duplicates are deduped, unmatched rules fire as notifications. Requirements: PHP 8.2+, Laravel 12/13, Filament 4/5. Known gaps: authorize(), withValidator(), passedValidation()/failedValidation() unsupported; wizard steps validate only active-step fields, so cross-step dependencies need mergeInput. Two things to check in the spike: whether prepareForValidation() actually works despite the README's limitations table (v1.3.0 claims it), and whether InteractsWithFormRequestValidation::getFormRequestValidated() fits our create-record flow. Budget: half a day to read the source, one day to pilot, one day to write the regression tests. If the spike is messy, we build the 40-line trait — the state-path normalization is the only nontrivial part."
For the sponsor signing off: success criteria for the pilot are concrete and cheap to evaluate — (1) one resource with shared store/update Form Requests validates identically in the API and the admin panel, (2) zero duplicated rule declarations for that resource, (3) no regression in error messages or field-level error placement, (4) upgrade to the next Filament minor doesn't break it. If all four hold, roll out to the remaining shared entities; if any fail, we've spent a sprint on a fork-vs-build decision we needed to make anyway.
How can I help you explore Laravel packages today?