Description
Symfony version(s) affected: 5.1
Description
When a CollectionType is a child element of a form type, that itself is used in a CollectionType, and both form types define a _widget block to override default rendering, then the block of the outer type is used for both (inner and outer form) types.
This will most likely produce an exception, as the inner form does not define the properties needed by the block of the outer form.
How to reproduce
A minimal reproducer can be found here: https://github.com/jbtronics/symfony_bug
Assume we have multiple forms:
- Our inner form:
class Element2Type extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
}
}
- A form which contains of a collection of Element2Type:
class Element1Type extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('id');
$builder->add('elements', CollectionType::class, [
'entry_type' => Element2Type::class,
]);
}
}
- And a form which contains Element1Type:
$builder->add('elements', CollectionType::class, [
'entry_type' => Element1Type::class
]);
If you now define custom styles for the elements
{% block element2_widget %}
Inner Element
{% endblock %}
{% block element1_widget %}
{# This block is called two times, one time for element1 (which is correct), and one time for element2 (which is wrong) #}
Outer Element
{{ form_widget(form.id) }}
{{ form_widget(form.elements) }}
{% endblock %}
then the code will break on Symfony 5.1, as element1_widget
block is used for rendering both Element1Type and Element2Type elements, which will throw an exception (Neither the property "id" nor one of the methods "id()", "getid()"/"isid()"/"hasid()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView"
).
Possible Solution
The bug was somehow introduced by pull #36088 (Added collectzion_entry block), and especially this line, as commenting this line, stops the wrong behavior.