[6.x] Forms 2: Unique Instances - #15255
Draft
duncanmcclean wants to merge 23 commits into
Draft
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
The configurable value shape is a non-empty array even when no form is selected, so `required` and `max_items` rules never failed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
Localizations inheriting the form field from their origin were getting no overrides, since `get()` only reads local data. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
The `_entry` input is user-editable, so submissions could be attached to any entry at all. Requiring the entry to reference the form keeps tampering equivalent to submitting from that entry's own page. Also translates the validation message. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
`pluck` reads from the Stache's indexed values (or a plain select on eloquent), so building the options no longer hydrates every submission. The badge now looks up a single entry instead of the whole options map. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
`FormFieldValues::on($entry)` walks the entry's blueprint and values, so entry overrides and submission validation find form fields inside nested fieldtypes rather than only at the top level. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
`Form::instance()` drops the entry unless the form has unique instances, which also covers the tag's hidden `_entry` input. The submission page only exposes the attached entry under the same conditions, matching the listing column and filter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
The configure stack shows the form's own values as synced origin values and tracks which fields have been deliberately desynced, so a toggle can be overridden off and only desynced fields are stored. This replaces the placeholder approach, and lets `required` and `max_items` validate against the actual form handles. The override value shape now also requires forms pro, which reaches the Vue component through preload meta. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MhgpB3C65heLNJs7YCSZqV
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HWzPmQoku8u1dA6VMp51RS
duncanmcclean
marked this pull request as draft
August 24, 2026 22:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request implements "unique instances" for forms: a Forms Pro feature which lets a form be treated as its own instance per entry, with submissions tracked against the entry they were submitted from, rather than in aggregate.
The classic use case is an Events collection where every event has its own RSVP form — each event gets its own submissions, its own capacity and its own close date, all from a single
rsvpform.Like multi-page forms, everything lives in core but is only available when the
statamic/forms-proaddon is installed.Enabling unique instances
Toggle on "Unique Instances" in the form's configure screen, then attach the form to entries using the
formfieldtype.The frontend
When
{{ form:create }}is rendered in an entry's context, it outputs a hidden_entryinput, and the submission is tracked against that entry.Per-entry restrictions & overrides
When unique instances is enabled, the form's Access settings are evaluated per entry:
Connections (#15063) will be overridable per entry in the same way, so each entry can have its own notifications.
CleanShot.2026-08-24.at.21.42.58.mp4
In the Control Panel
The submissions listing shows which entry each submission came from, and can be filtered down to a single entry.
On the entry's publish form, the form fieldtype has a "View Submissions" option which opens the entry's submissions in a stack, with individual submissions opening in a nested stack. The fieldtype's index view links to the pre-filtered submissions listing, and the submission page links back to the entry.
PHP API
The form fieldtype's value is stored as a plain handle until an entry has overrides, at which point it becomes an array with
formandconfigkeys.Restriction logic lives on a new
Instanceclass, since "is this form open?" becomes a per-entry question when unique instances is enabled:Depends on: #15063