diff --git a/src/Symfony/Component/Form/AbstractRendererEngine.php b/src/Symfony/Component/Form/AbstractRendererEngine.php index 5d7416d2a8..9e16b44cfe 100644 --- a/src/Symfony/Component/Form/AbstractRendererEngine.php +++ b/src/Symfony/Component/Form/AbstractRendererEngine.php @@ -21,7 +21,7 @@ abstract class AbstractRendererEngine implements FormRendererEngineInterface /** * The variable in {@link FormView} used as cache key. */ - const CACHE_KEY_VAR = 'full_block_name'; + const CACHE_KEY_VAR = 'cache_key'; /** * @var array diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php index 5deadf429a..c96ed1382f 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php @@ -129,6 +129,13 @@ class FormType extends AbstractType 'compound' => $form->getConfig()->getCompound(), 'types' => $types, 'translation_domain' => $translationDomain, + // Using the block name here speeds up performance in collection + // forms, where each entry has the same full block name. + // Including the type is important too, because if rows of a + // collection form have different types (dynamically), they should + // be rendered differently. + // https://github.com/symfony/symfony/issues/5038 + 'cache_key' => $fullBlockName . '_' . $form->getConfig()->getType()->getName(), )); } diff --git a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php index 75e8e193e4..163539522b 100644 --- a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType; abstract class AbstractDivLayoutTest extends AbstractLayoutTest { @@ -283,6 +284,29 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest ); } + // https://github.com/symfony/symfony/issues/5038 + public function testCollectionWithAlternatingRowTypes() + { + $data = array( + array('title' => 'a'), + array('title' => 'b'), + ); + $form = $this->factory->createNamed('name', 'collection', $data, array( + 'type' => new AlternatingRowType(), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div[./div/div/input[@type="text"][@value="a"]] + /following-sibling::div[./div/div/textarea[.="b"]] + ] + [count(./div[./div/div/input])=1] + [count(./div[./div/div/textarea])=1] +' + ); + } + public function testEmptyCollection() { $form = $this->factory->createNamed('name', 'collection', array(), array( diff --git a/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php b/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php new file mode 100644 index 0000000000..e53d19ffe9 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php @@ -0,0 +1,27 @@ +getFormFactory(); + + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) { + $form = $event->getForm(); + $type = $form->getName() % 2 === 0 ? 'text' : 'textarea'; + $form->add($formFactory->createNamed('title', $type)); + }); + } + + public function getName() + { + return 'alternating_row'; + } +}