diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index 5799a29757..a94752e130 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -200,6 +200,8 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c model * added options "adder_prefix" and "remover_prefix" to collection and choice type + * forms now don't create an empty object anymore if they are completely + empty and not required. The empty value for such forms is null. ### HttpFoundation diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php b/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php index abbe558208..1de3b1dc97 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php @@ -156,7 +156,11 @@ class FieldType extends AbstractType } if ($class) { - $defaultOptions['empty_data'] = function () use ($class) { + $defaultOptions['empty_data'] = function (FormInterface $form) use ($class) { + if ($form->isEmpty() && !$form->isRequired()) { + return null; + } + return new $class(); }; } else { diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index b714fb5056..a4403f494e 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -517,7 +517,7 @@ class Form implements \IteratorAggregate, FormInterface } // Merge form data from children into existing client data - if (count($this->children) > 0 && $this->dataMapper) { + if (count($this->children) > 0 && $this->dataMapper && null !== $clientData) { $this->dataMapper->mapFormsToData($this->children, $clientData); } diff --git a/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php b/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php index 879d4fd35a..16644b0b7e 100644 --- a/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php +++ b/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php @@ -178,18 +178,52 @@ class FieldTypeTest extends TypeTestCase { $form = $this->factory->create('form', null, array( 'data_class' => 'Symfony\Tests\Component\Form\Fixtures\Author', + 'required' => false, )); $form->add($this->factory->createNamed('field', 'firstName')); + $form->add($this->factory->createNamed('field', 'lastName')); $form->setData(null); - $form->bind(array('firstName' => 'Bernhard')); + // partially empty, still an object is created + $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; + $author->setLastName(''); $this->assertEquals($author, $form->getData()); } + public function testBindEmptyWithEmptyDataCreatesNoObjectIfNotRequired() + { + $form = $this->factory->create('form', null, array( + 'data_class' => 'Symfony\Tests\Component\Form\Fixtures\Author', + 'required' => false, + )); + $form->add($this->factory->createNamed('field', 'firstName')); + $form->add($this->factory->createNamed('field', 'lastName')); + + $form->setData(null); + $form->bind(array('firstName' => '', 'lastName' => '')); + + $this->assertNull($form->getData()); + } + + public function testBindEmptyWithEmptyDataCreatesObjectIfRequired() + { + $form = $this->factory->create('form', null, array( + 'data_class' => 'Symfony\Tests\Component\Form\Fixtures\Author', + 'required' => true, + )); + $form->add($this->factory->createNamed('field', 'firstName')); + $form->add($this->factory->createNamed('field', 'lastName')); + + $form->setData(null); + $form->bind(array('firstName' => '', 'lastName' => '')); + + $this->assertEquals(new Author(), $form->getData()); + } + /* * We need something to write the field values into */