Breaking: #73717 - ObjectStorage validation results keyed by position
See forge#73717
Description
\TYPO3\ builds the
property path of a collection element from the key the collection yields while
iterating. For
\TYPO3\ that key is
the
spl_ of the element, so validation results ended up
below a path such as
toppings..
Form field ViewHelpers address the same element by its position instead, as in
<f:. Producer and consumer
therefore never agreed on the same path.
Elements of an
Object are now keyed by their position, the same
way a plain array already behaved.
Impact
Validation results of
Object elements are now addressed by the
position of the element:
$result->forProperty('toppings.0.title')->getErrors();
Code and Fluid templates that relied on the object hash no longer find these results and silently render nothing, because an unknown property path resolves to an empty result object.
In exchange, the property path of a validation result now matches the property
path used by the form field ViewHelpers. The
error of a form field
inside a collection therefore works without further ado, and
<f: can be addressed with the very same path
that names the field.
Affected installations
Installations with Extbase forms that edit a collection of child objects and
render validation results per element. Such templates are recognizable by an
<f: that passes its
key
into a validation result lookup,
while the form fields below it use the iteration index:
<f:for each="{pizza.toppings}" as="topping" iteration="i" key="key">
<f:form.validationResults for="pizza.toppings.{key}.title">
<f:form.textfield property="toppings.{i.index}.title" />
</f:form.validationResults>
</f:for>
Installations that render validation results only for non-collection properties are not affected.
Migration
Use the iteration index for the validation result as well, which makes the second addressing scheme obsolete:
<f:for each="{pizza.toppings}" as="topping" iteration="i">
<f:form.validationResults for="pizza.toppings.{i.index}.title">
<f:form.textfield property="toppings.{i.index}.title" />
</f:form.validationResults>
</f:for>
Where the lookup was only used to set an error class on the field, it can be dropped entirely and left to the field itself:
<f:form.textfield property="toppings.{i.index}.title"
errorClass="has-error" />