symfony: PropertyPathMapper crashing with CollectionType when framework.property_access.throw_exception_on_invalid_index is true
Symfony version(s) affected: 3.4.*|4.* (Probably also 2.7+?)
Description
If you enable the option in the framework to throw exceptions on invalid index for the propery accessor:
framework:
property_access:
throw_exception_on_invalid_index: true
(Which I think should be the default behavior by the way, but this is outside the scope of this bug)
When you have a form using a CollectionType, the PropertyPathMapper will crash when trying to access invalid indexes when the ResizeFormListener adds a new field to the form. (Which happens when you add an element to your collection)
How to reproduce
On a Symfony 3.4 standard edition, enable the throw_exception_on_invalid_index option as mentionned before.
Then use this code in the DefaultController
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*
* @param Request $request
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function indexAction(Request $request)
{
$formBuilder = $this->createFormBuilder(['collection' => ['test']]);
$formBuilder->add(
'collection',
CollectionType::class,
[
'allow_add' => true,
'entry_type' => TextType::class,
]
);
$form = $formBuilder->getForm();
$form->handleRequest($request);
return $this->render(
'default/index.html.twig',
[
'form' => $form->createView(),
]
);
}
}
And this code for the template:
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="text" name="form[collection][1]" value="invalid index">
<button type="submit">Submit</button>
{{ form_end(form) }}
{% endblock %}
This adds the element manually because this a the simplest way to test this.
Submit : Crash
Cannot read index "1" while trying to traverse path "[1]". Available indices are "Array
(
[0] => 0
)
".
Possible Solutions
There are many way to tackle this problem :
- Remove the
throw_exception_on_invalid_indexoption if it’s not meant to be used (I’m against this because I think it should be true by default) - Inject a custom
PropertyAccessorin thePropertyPathMapper; notform.property_accessor. (I find this solution a bit strange) - Make the
form.property_accessorignore any settings from theframework.property_accessor.\*configuration. - Catch the exception properly inside the
PropertyPathMapper - Create a custom
CollectionPropertyPathMapperonly for theCollectionTypethat uses a dedicated property accessor that ignores the global setting. - Create a custom
CollectionPropertyPathMapperonly for theCollectionTypethat catches the exception properly. (I’m in favor of this one)
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 3
- Comments: 16 (6 by maintainers)
After reviewing this issue in Symfony 4.4, I discovered that a new feature was introduced in v4.3: https://github.com/symfony/symfony/issues/30536
The option
throw_exception_on_invalid_property_pathdefaults to true and do exactly what it’s supposed to do: Throwing exceptions on invalid property paths but allowing write access to non-existing indices.I’m closing this issue as the 3.* branch is not supported anymore so this is now irrelevant.
I will try to create a PR soon using the solution proposed by @xabbuh
@alamirault or anyone stumbling upon this issue, I’ll provide a PR when I have time, meanwhile you can install sidus/base-bundle for a quick fix.