Open source
Forms for Laravel
composer require roundly-consulting/forms-for-laravelOverview
A native form engine for Laravel. Define multi-step forms — forms, groups and fields — as data in your database, validate input against per-field rules, and store every submission, tied to whoever sent it. Build forms with a fluent builder or sync them from config, save and resume drafts, read answers back typed, accept file uploads as private media and route submissions to the reviewers you name. MIT licensed and built only on Laravel and Roundly’s own open-source packages — no third-party form vendors.
What you get
Forms as data
Forms, groups (steps) and fields live in your database — change a form without shipping code or redeploying.
Fluent builder & config sync
Define a whole form in one transactional call, edit it with a diffing updater, or declare it in config and run forms:sync.
Conditional validation
Per-field Laravel rules, custom messages, and fields that are shown or required only when another answer matches.
Drafts & closed forms
Save and resume partial submissions, finalize with full validation, and reject submissions to private or expired forms.
Typed answers & uploads
Answers read back as int, bool, dates and arrays; file fields store uploads as private media with signed URLs.
Submission review
Route a whole submission to the reviewers you name — unanimous, any, quorum or weighted — with status mirrored back.
Facade, DI or actions
Call the Forms facade, inject FormsManager or run single-purpose actions — Forms::fake() records every call and still performs it.
Documentation
Installation
Install via Composer, publish and run the migrations (including the dependency packages’), and optionally publish config and translations.
Configuration
Every config key and its default — swappable models, sender key type, field resolvers, typed field types, media uploads and reviews.
The Forms facade
The whole API on one facade — define, find, validate, submit, draft, finalize, read and review forms, plus fluent builders and handles.
DI and actions
Prefer explicit dependencies? Inject FormsManager for the same API, or call the single-purpose actions behind each facade method.
Form structure
Forms hold ordered groups (steps), groups hold fields. Create them as plain Eloquent models and read the dotted field path.
Fluent form builder
Define a whole form — groups and fields — in one transactional call with Forms::define(), typed shortcuts and custom messages.
Conditional fields
Show or require a field only when another answer matches — hidden fields are skipped by validation automatically.
Validating & submitting
Find a form, validate request input against each field’s rules, and store a submission for every field under one reference uuid.
Drafts (save & resume)
Save a partial submission without validation, resume it by uuid, and finalize it later with full validation.
Reading submissions
Read submissions back as one keyed, typed answer set each — filtered by sender, uuid or review outcome — or fetch one by its uuid.
Editing forms
Diff a new definition against the stored structure and save only what changed — events fire only for changed records.
Typed field values
Each field type maps to a value type, so answers read back as int, bool, dates or arrays and mismatches fail validation.
File uploads
file and image fields store uploads as private media on the submission row — image variants, passthrough files and signed URLs.
Submission review
Route a whole submission to the reviewers you name — unanimous, any, quorum or weighted — with its status mirrored back.
The HasForms trait
Give your user (or any sender) model a submissions relation plus submitTo() and draftTo() shortcuts.
Declarative forms
Declare forms in config/forms.php and sync them into the database idempotently with php artisan forms:sync.
Resolvers & autofill
Control how a field type reads from the request and from storage with a custom resolver, and pre-fill fields with Autofill classes.
API resources
Render a form and its groups and fields as JSON for SPA or mobile frontends with the bundled JsonResources.
Events
React to submissions, structure changes and review outcomes — FormSubmitted, Form/Group/Field lifecycle and review events.
Exceptions
Package-specific, catchable exceptions — all extending FormsException — with translatable messages you can override.
Models, scopes & soft deletes
Query scopes for public, active and expired forms, recoverable soft deletes, and swapping any model for your own subclass.
Artisan commands
Sync config-defined forms with forms:sync and inspect the package setup in php artisan about.
Testing
Assert form activity with Forms::fake() — a recording fake that still performs — plus InteractsWithForms helpers, Pest matchers and factories.
Requirements
PHP 8.4+ and Laravel 12 or 13; enums, attributes, media library and approvals packages install automatically.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.