Skip to content

Navigation Menu

Sign in
Appearance settings
Sign up
Appearance settings

[Form] Add an allow_array_submission option to let PRE_SUBMIT listeners transform submitted arrays - #65515

#65515
Open
nicolas-grekas wants to merge 1 commit into
symfony:8.2symfony/symfony:8.2from
nicolas-grekas:sweep/47093-form-presubmit-array-datanicolas-grekas/symfony:sweep/47093-form-presubmit-array-dataCopy head branch name to clipboard
Open

[Form] Add an allow_array_submission option to let PRE_SUBMIT listeners transform submitted arrays#65515
nicolas-grekas wants to merge 1 commit into
symfony:8.2symfony/symfony:8.2from
nicolas-grekas:sweep/47093-form-presubmit-array-datanicolas-grekas/symfony:sweep/47093-form-presubmit-array-dataCopy head branch name to clipboard

Conversation

@nicolas-grekas

@nicolas-grekas nicolas-grekas commented Aug 20, 2026

Copy link
Copy Markdown
Member
Q A
Branch? 8.2
Bug fix? no
New feature? yes
Deprecations? no
Issues Fix #47093
License MIT

Form::submit() rejects array data submitted to a form that is neither compound nor multiple. It does so before PRE_SUBMIT is dispatched: the data is replaced by null, a TransformationFailedException is recorded, and listeners are never called. Applications that submit JSON payloads cannot map such a payload to a scalar field, because no listener ever sees the value.

This PR adds an allow_array_submission option to FormType, defaulting to false.

When the option is enabled, the check moves after PRE_SUBMIT: listeners receive the submitted array and can replace it with data the form accepts. The deferred check then applies the same rules as the eager one. Data that is still an array fails with the same exception message as today, unless a listener turned it into a file upload: such data is accepted when allow_file_upload is true, and reported as "file upload given" otherwise, which is what the same value gets when it is submitted directly. The option mirrors allow_file_upload, which gates the sibling branch of the same check.

When the option is left to false, nothing changes: listeners are not called for array data, and the form fails exactly as before, with the same message and the same null view data.

Why opt-in

An earlier revision of this PR moved the check unconditionally and targeted 6.4 as a bugfix. That changes the input domain of every deployed PRE_SUBMIT listener on a scalar field: any client can post field[]=x, so listeners written against the "never an array" guarantee become reachable with client-controlled arrays. Three core types needed guards for exactly that reason, and third-party listeners would have been exposed the same way with no guard at all. The option keeps the old guarantee unless a form opts in, and scopes the new listener contract to that form.

Core listeners

With the option enabled, the listeners registered by core types can receive arrays too, so the three affected ones now handle them:

  • FileType with multiple: false replaces anything that is not a file upload by null, so an array would validate as "no file uploaded" with no error at all. It now leaves arrays alone, so the form reports them.
  • ColorType with html5: true added its own "This value is not a valid HTML5 color." error for arrays, even when a later listener turned the value into a valid color. It now skips arrays, so the html5 check applies to values a listener has normalized.
  • TimeType with widget: single_text passed the submitted value straight to preg_match(), which raises a TypeError on arrays. Both of its listeners now check for a string first, and the form reports "Please enter a valid time." instead.

The FileType and ColorType guards are gated on the option, so a form that does not opt in keeps the behavior it has today, including for an array set by a PRE_SUBMIT listener registered at a priority above 0. The TimeType guard is not gated: an array can reach those listeners today through such a priority, and a TypeError is never the right report.

On a ChoiceType field that is neither multiple nor expanded and that enables the option, the type's own PRE_SUBMIT listener runs first: a nested invalid array is reported as "All choices submitted must be NULL, strings or ints.", and an array that survives the listener is rejected by the deferred check. Nothing changes for choice fields that do not enable the option.

Checks

Run on this branch with PHP 8.5 and PHPUnit 13.3:

  • ./phpunit src/Symfony/Component/Form: 5100 tests, 10773 assertions, 384 skipped, 8 incomplete, no failure. The base commit runs 5085 tests with the same skipped and incomplete counts.
  • php-cs-fixer on the files this PR touches: clean.
  • The console descriptor fixtures were regenerated, since they list the options of FormType.

Revert verified, running the same suite in three states:

  • All source files restored to their 8.2 state, tests kept: 7 errors and 8 failures. The tests that pass the new option error with The option "allow_array_submission" does not exist, the four descriptor fixtures no longer match, and the SimpleFormTest cases built on a raw FormBuilder fail on their behavior assertions. testArrayDataIsRejectedBeforeListenersByDefault, ColorTypeTest::testArraySetByPreSubmitListenersIsReportedWhenNotAllowed and FileTypeTest::testArraySetByPreSubmitListenersIsDiscardedWhenNotAllowed still pass, since they protect existing behavior.
  • Only the three type files restored: 2 errors and 5 failures. TimeTypeTest raises TypeError: preg_match(): Argument #2 ($subject) must be of type string, array given, ColorTypeTest::testSubmitArrayWhenAllowed gets "This value is not a valid HTML5 color." instead of "Please select a valid color.", and the FileTypeTest cases report the form as synchronized or lose the resolved upload.
  • This branch: no failure.

For the documentation

  • Document allow_array_submission in the form options reference: what it enables, default false.
  • Show the JSON payload use case: a PRE_SUBMIT listener that maps the submitted array to the field's scalar value.
  • Note that enabling the option means every PRE_SUBMIT listener on that form must be ready to receive an array; core type listeners already are.
  • Note that a listener may also resolve an array to a file upload, which the form accepts when allow_file_upload is true.

@nicolas-grekas nicolas-grekas added this to the 6.4 milestone Aug 20, 2026
@nicolas-grekas
nicolas-grekas force-pushed the sweep/47093-form-presubmit-array-data branch from 04917f7 to cb952fd Compare August 21, 2026 15:23
@nicolas-grekas
nicolas-grekas changed the base branch from 6.4 to 8.2 August 22, 2026 08:30
@nicolas-grekas
nicolas-grekas force-pushed the sweep/47093-form-presubmit-array-data branch from cb952fd to 44c031d Compare August 22, 2026 08:30
@nicolas-grekas nicolas-grekas removed this from the 6.4 milestone Aug 22, 2026
@nicolas-grekas nicolas-grekas added this to the 8.2 milestone Aug 22, 2026
@nicolas-grekas nicolas-grekas changed the title [Form] Let PRE_SUBMIT listeners turn submitted arrays into scalar data [Form] Add an allow_array_submission option to let PRE_SUBMIT listeners transform submitted arrays Aug 22, 2026
@nicolas-grekas

Copy link
Copy Markdown
Member Author

I reworked this as an opt-in feature on 8.2, through a new allow_array_submission option that defaults to false.

Moving the check after PRE_SUBMIT unconditionally changes what every deployed listener on a scalar field can receive, and any client can trigger that by posting field[]=x. On the current code the stored failure is thrown before the event is dispatched, so such listeners never see arrays at all. The reordering itself is what made the TimeType TypeError, the FileType silent acceptance and the ColorType error reachable, and a core patch can only fix the core listeners, not third-party ones. That ruled out shipping the reordering as a 6.4 bugfix.

The option mirrors allow_file_upload, which already gates the sibling branch of the same check. With the option left to its default, behavior is unchanged, including the ChoiceType message that the earlier revision modified.

Comment thread src/Symfony/Component/Form/Form.php
Comment thread src/Symfony/Component/Form/Extension/Core/Type/FileType.php Outdated
Comment thread src/Symfony/Component/Form/Extension/Core/Type/ColorType.php Outdated
@nicolas-grekas
nicolas-grekas force-pushed the sweep/47093-form-presubmit-array-data branch 2 times, most recently from d587ff2 to e1922b5 Compare August 24, 2026 07:35
…ers turn a submitted array into data the form accepts
@nicolas-grekas
nicolas-grekas force-pushed the sweep/47093-form-presubmit-array-data branch from e1922b5 to 51d7ec4 Compare August 24, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't transform array data in PreSubmit event or DataTransformer

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.